esxcli storage core path list: reading and fixing ESXi storage paths

When a datastore goes read only at 02:00, or a LUN that used to have four paths suddenly has three, the answer is almost always in two commands: esxcli storage core path list tells you the physical state of every path the host can see, and esxcli storage nmp device list tells you which policy is choosing between them. Everything else in the ESXi storage stack is built on those two readings.

The commands themselves are easy. What costs people an evening is that the output is a stanza format that resists every one line filter, that esxcli storage core path set can read a dead state but cannot write one, and that the two obvious ways to change a path policy behave completely differently: one takes effect now and pins the device forever, the other changes nothing on the devices you already have until the host reboots or the device is reclaimed.

This page covers the reading commands, the two writing commands and the boundaries between them, with the parsing behaviour measured rather than assumed. If you want the esxcli grammar itself, the option forms and the machine readable output modes, start with esxcli on ESXi: syntax, output formatters and remote execution.

Applies to: ESXi 7.0 / 8.0 / 9.0, with version differences called out where the documentation states one.


Quick answer

Three commands answer most storage path questions. Run them in this order: the paths and their states, the policy that is choosing between them, then a rescan that updates path state and removes dead paths.

# Every path on the host, with its state. Add -d to limit it to one device.
esxcli storage core path list -d naa.6006016012345678a1b2c3d4e5f60001

# Which SATP and which path selection policy NMP applied to that device.
esxcli storage nmp device list -d naa.6006016012345678a1b2c3d4e5f60001

# Rescan all HBAs: this also reclaims paths and updates their state.
esxcli storage core adapter rescan --all
Note: If the host answers with a connection failure, hostd is not running. The Broadcom KB for LUN pathing says to use localcli instead in that situation.

What the PSA stack shows, and which command shows what

ESXi discovers physical paths at boot and on every adapter rescan. A set of claim rules then decides which multipathing module owns the paths to each device: the Native Multipathing Plugin (NMP), the High Performance Plugin (HPP), or a third party module. The vSphere Storage documentation adds one detail worth remembering when a change does not appear immediately: by default the host performs a periodic path evaluation every five minutes and assigns unclaimed paths to the appropriate module.

For devices owned by NMP, a second set of claim rules applies. A Storage Array Type Plugin (SATP) decides how failover is handled for that array, and a Path Selection Plugin (PSP) decides which physical path each I/O goes down. That split is why two different commands are needed to answer what looks like one question.

QuestionCommandNamespace
Which physical paths exist and what state is each one in?esxcli storage core path listcore
Which devices are registered with the PSA at all?esxcli storage core device listcore
Which HBAs does the host have?esxcli storage core adapter listcore
Which SATP and PSP did NMP give this device?esxcli storage nmp device listnmp
Which SATPs are loaded and what are their claim rules?esxcli storage nmp satp listnmp
How much I/O and how many failures went down each path?esxcli storage core path stats getcore
Pre-condition: The core namespace answers for every path on the host. The nmp namespace only answers for devices NMP actually owns. A device claimed by HPP is invisible to every nmp command, which is the subject of a section further down.

Before the first example

Four things have to be true before any of the examples below will return something useful. Each one is a single command.

1. A shell on the host. Either SSH to the ESXi host, or use the DCUI shell. The commands on this page are host commands, not vCenter commands. This one confirms you are in the right place, because the reference describes it as listing the loaded PSA plugins on the system:

# Should print the loaded multipathing and filter plugins.
# If this returns nothing useful you are not on an ESXi host shell.
esxcli storage core plugin list

2. At least one HBA with storage behind it. If the adapter list is empty or your array HBA is missing, nothing further will work:

# Lists every storage HBA the host knows about, including vmhba names.
esxcli storage core adapter list

3. A device identifier to work with. The documentation is explicit about which identifier to use: use industry standard device names, with format eui.xxx or naa.xxx, to ensure consistency, and do not use VML LUN names unless device names are not available. It also warns that names of virtual machine HBAs are not guaranteed to be valid across reboots.

# Pick one device identifier from this list and use it for the rest of the session.
esxcli storage core device list

4. A written down starting state. Before you change anything, record the current policy so you can put it back. This is the only prerequisite that is about you rather than the host:

# Save the current SATP and PSP for the device before any change.
esxcli storage nmp device list -d naa.6006016012345678a1b2c3d4e5f60001 > /tmp/before.txt
Common mistake: Every example on this page uses the same device, naa.6006016012345678a1b2c3d4e5f60001, and the same two adapters, vmhba2 and vmhba3. Substitute your own identifier once, at the top, rather than per example. A path operation aimed at the wrong device is not always reversible in the way you expect.

Practical examples

Example 1: read the state of every path to one device

The problem: A datastore is still mounted but performance has collapsed, and the vSphere Client shows the device with fewer active paths than the other hosts in the cluster.

The solution: esxcli storage core path list -d prints one stanza per path. The field that matters is State; the field that identifies the path to a human is Runtime Name.

# -d limits the output to one device, which on a busy host is the difference
# between two stanzas and two hundred.
esxcli storage core path list -d naa.6006016012345678a1b2c3d4e5f60001

Each stanza looks like this. The field names and their order below are exactly those published in the Broadcom KB on obtaining LUN pathing information; the identifiers and WWNs are lab values, because the KB redacts its own. The capture Broadcom publishes is of a healthy path, so that is what this page prints:

fc.20000000c9aa1111:10000000c9aa1111-fc.5006016012345678:5006016812345678-naa.6006016012345678a1b2c3d4e5f60001
   UID: fc.20000000c9aa1111:10000000c9aa1111-fc.5006016012345678:5006016812345678-naa.6006016012345678a1b2c3d4e5f60001
   Runtime Name: vmhba2:C0:T0:L10
   Device: naa.6006016012345678a1b2c3d4e5f60001
   Device Display Name: DGC Fibre Channel Disk (naa.6006016012345678a1b2c3d4e5f60001)
   Adapter: vmhba2
   Channel: 0
   Target: 0
   LUN: 10
   Plugin: NMP
   State: active
   Transport: fc
   Adapter Identifier: fc.20000000c9aa1111:10000000c9aa1111
   Target Identifier: fc.5006016012345678:5006016812345678
   Adapter Transport Details: WWNN: 20:00:00:00:c9:aa:11:11 WWPN: 10:00:00:00:c9:aa:11:11
   Target Transport Details: WWNN: 50:06:01:60:12:34:56:78 WWPN: 50:06:01:68:12:34:56:78
Note: Plugin is the field that tells you which multipathing module owns this path. If it reads anything other than NMP, the esxcli storage nmp commands later on this page will not return this device.
Warning: Broadcom does not publish a complete list of path state values on the path commands reference page. It documents active and off as the two states an administrator can set, and it documents DEAD paths as something an adapter rescan removes. On a failed path the field that changes is State, which is why every filter on this page keys on that one line.

Example 2: find which paths are dead, not just how many

The problem: You know the host has dead paths. You need their runtime names so you can tell the SAN team which ports to look at.

The solution: The obvious grep counts them but cannot name them, because the state and the runtime name are on different lines of the same stanza. Pair them with awk instead.

This is what the obvious approach returns. Run against a two path capture where one path is dead, it prints the state line and nothing that identifies the path:

# The obvious filter. It finds the dead path but throws away its identity.
esxcli storage core path list | grep -i "State: dead"
   State: dead

Carrying the runtime name forward and printing it when the state line arrives gives the answer you actually wanted:

# Remember the runtime name from each stanza, then print it when the state line
# for that same stanza arrives. Anchoring both patterns with ^ and a space class
# stops them matching an identifier that happens to contain the same text.
esxcli storage core path list | awk '/^ *Runtime Name:/{rn=$3} /^ *State:/{print rn" "$2}'

# Same idea, filtered to the dead ones only.
esxcli storage core path list | awk '/^ *Runtime Name:/{rn=$3} /^ *State:/ && $2=="dead"{print rn}'
vmhba2:C0:T0:L10 active
vmhba3:C0:T1:L10 dead
Note: Both one liners here were run against the documented output shape in a POSIX shell, not on an ESXi host. The awk features used are the portable ones: a saved variable, two anchored patterns and positional fields.

Example 3: disable a path for SAN maintenance, then enable it again

The problem: The storage team is replacing an FC switch and wants the host to stop using the paths through it, without unpresenting the LUN.

The solution: esxcli storage core path set toggles a single path between active and off. Set it off before the work starts and active again afterwards.

# Administratively disable one path. The runtime name comes from path list,
# so check it first: this operation is per path, not per device.
esxcli storage core path set --state off --path vmhba3:C0:T1:L10

# When the switch work is finished, put it back.
esxcli storage core path set --state active --path vmhba3:C0:T1:L10
Common mistake: The reference is explicit that you cannot set a path to dead. The user is not able to change the full range of path states, but can toggle between active and off. There is no command here that repairs a broken path; dead is something the array and the fabric decide, and something an adapter rescan clears once it is genuinely gone.
Warning: Two documented refusals apply. The VMkernel will not change a path’s state if the change would cause an all paths down state, or if the device is currently in use, so disabling the only path to a device is likely to fail. Separately, the change operation fails if I/O is active when the path setting is changed: the documented response is to reissue the command, and at least one I/O operation must be issued before the change takes effect.

Example 4: read the path policy and change it for one device

The problem: One LUN is using a single path while its siblings are load balancing. You want to see what policy it has and move it to round robin.

The solution: esxcli storage nmp device list reports the SATP and the PSP. esxcli storage nmp device set overrides the PSP for that one device.

# Read first. Storage Array Type is the SATP, Path Selection Policy is the PSP.
esxcli storage nmp device list -d naa.6006016012345678a1b2c3d4e5f60001

The field names below are again those published in the Broadcom LUN pathing KB, with lab identifiers substituted. The device is on the fixed policy, and Working Paths names a single path:

naa.6006016012345678a1b2c3d4e5f60001
   Device Display Name: DGC Fibre Channel Disk (naa.6006016012345678a1b2c3d4e5f60001)
   Storage Array Type: VMW_SATP_ALUA
   Storage Array Type Device Config: SATP VMW_SATP_ALUA does not support device configuration.
   Path Selection Policy: VMW_PSP_FIXED
   Path Selection Policy Device Config: {preferred=vmhba2:C0:T0:L10;current=vmhba2:C0:T0:L10}
   Path Selection Policy Device Custom Config:
   Working Paths: vmhba2:C0:T0:L10
# Set this one device to round robin. --device is required, --psp names the
# policy. Run 'esxcli storage nmp psp list' first if you are unsure what is loaded.
esxcli storage nmp device set --device naa.6006016012345678a1b2c3d4e5f60001 --psp VMW_PSP_RR

# Read it back. Path Selection Policy should now read VMW_PSP_RR.
esxcli storage nmp device list -d naa.6006016012345678a1b2c3d4e5f60001
Result: The KB notes that with the round robin policy, the paths listed under Working Paths are the ones the storage array is presenting as active. That is why the field can name fewer paths than esxcli storage core path list shows as active for the device.
Common mistake: This command looks like the harmless way to fix one LUN, and it has a permanent side effect. See the next section before you run it across an array.

Example 5: clear the dead paths and confirm nothing is left

The problem: The SAN work is finished, the fabric is healthy, but the host still lists dead paths and dead devices from the old configuration.

The solution: An adapter rescan is the documented way to remove dead paths and update path state. Its --type option lets you do only that, rather than a full discovery pass.

--type valueWhat the reference says it doesWhen to use it
allPerform rescan and do all operations. This is the default action.After presenting new LUNs
addPerform rescan and only add new devices if any.New LUNs only, leave everything else alone
deletePerform rescan and only delete DEAD devices.Cleanup after an unpresent
updateRescan existing paths only and update path states.Cheapest way to refresh state after fabric work
# Refresh the state of existing paths without a full discovery pass.
esxcli storage core adapter rescan --all --type update

# Then remove what is genuinely gone.
esxcli storage core adapter rescan --all --type delete

# Verify: this should now print nothing at all.
esxcli storage core path list | awk '/^ *Runtime Name:/{rn=$3} /^ *State:/ && $2=="dead"{print rn}'
Result: An empty result from that last command is the confirmation. If runtime names are still printed, these are not stale entries that a rescan can clear, and the next place to look is the host log. The ESXi and vCenter folders, tools and logs guide has the paths.
Note: A full rescan is heavier than it looks. The reference describes esxcli storage core adapter rescan as also running a claim operation equivalent to the claimrule run command, so it is not the cheap operation it looks like. How to rescan storage on an ESXi host covers the rescan itself in more detail.
Warning: The same reference page contradicts itself about the filesystem scan. The description of storage core adapter rescan says the operation will also run a filesystem rescan, while its own option table describes --skip-fs-scan as deprecated because no filesystem scan is performed by default. Both statements are on the same page. If you need a filesystem rescan, run esxcli storage filesystem rescan explicitly rather than assuming the adapter rescan did it.

Two commands set the path policy, and only one takes effect now

There are two commands that look like they do the same thing. One sets the default PSP for a Storage Array Type Plugin, the other overrides the PSP for a single device. They are documented to behave in opposite ways, and the difference is the single most expensive thing to get wrong on this page.

# A: change the SATP default. Affects every device on that SATP that has no
# explicit PSP of its own.
esxcli storage nmp satp set --satp VMW_SATP_ALUA --default-psp VMW_PSP_RR

# B: override the PSP on one device.
esxcli storage nmp device set --device naa.6006016012345678a1b2c3d4e5f60001 --psp VMW_PSP_RR

What the documentation states about each:

  • A, the SATP default. If a device does not have a specific PSP set, it always uses the PSP assigned to the SATP. If the default PSP for the SATP changes, the PSP assigned to the device changes only after reboot or after a device is reclaimed. Broadcom’s own KB on changing the default pathing policy ends its procedure with a reboot step.
  • B, the device override. If you use esxcli storage nmp device set to override the SATP’s default PSP with a specific PSP, the PSP changes immediately and remains the user defined PSP across reboots. A change in the SATP’s PSP has no effect.
  • Reclaiming, the way to apply A without a reboot. A device is reclaimed when you unclaim all paths for the device and reclaim the paths. esxcli storage core claiming reclaim --device attempts to unclaim all paths to a device and then run the loaded claim rules on each of the paths unclaimed to attempt to reclaim them.
Common mistake: Running B on every LUN because A appeared to do nothing is the trap. B works, so it feels like the correct command. What it actually does is pin every one of those devices to a user defined PSP, permanently, so that the array default you set in A will never reach them again, on this host, after any future reboot. Six months later the array vendor changes its recommended policy, you update the SATP default across the cluster, and every device you touched that day quietly ignores it.

The way out, if it has already happened, is documented and is a single flag. --default sets the path selection policy back to the default for the assigned SATP for that device, which puts the device back under the SATP’s control:

# Hand the device back to its SATP's default policy. -E is the short form.
esxcli storage nmp device set --default --device naa.6006016012345678a1b2c3d4e5f60001
Note: The rules that decide which SATP a device gets are the ones esxcli storage nmp satp rule list prints. The vSphere Storage documentation gives the search order, and notes that device rules are mutually exclusive with vendor and model rules and with driver rules: when searching the SATP rules to locate a SATP for a given device, NMP searches the driver rules first; if there is no match the vendor and model rules are searched, and finally the transport rules; if there is still no match, NMP selects a default SATP for the device.
Rule typeSearchedNote from the documentation
DriverFirstThe first place NMP looks
Vendor and modelSecondAdded with -V and -M, as in the documented sample rule
TransportThirdAdded with -R
Default SATPIf nothing matchedThe default SATP for an active-active FC array with a vendor and model not listed in the SATP rules is VMW_SATP_DEFAULT_AA
Warning: Broadcom’s own KB on changing PSP for multiple LUNs carries a warning worth repeating: changing the default pathing policy for a specific SATP when there are multiple storage arrays using the same plugin can cause other issues, such as incorrect pathing policies and unexpected storage failover results.

When a device is missing from nmp device list

A device that appears perfectly normally in esxcli storage core device list and has working paths in esxcli storage core path list can be completely absent from esxcli storage nmp device list. Nothing is broken. NMP simply does not own it.

The vSphere Storage documentation for the High Performance Plugin states the split by version, and it changed:

  • The HPP replaces NMP for high speed devices such as NVMe, and it is the default plugin that claims NVMe-oF targets.
  • In vSphere 8.0, the HPP is the default plugin that claims local NVMe and SCSI devices, and NVMe-oF targets, and you can replace it with NMP if necessary.
  • In vSphere 7.0 Update 1 and earlier, NMP remains the default plugin for local NVMe and SCSI devices, but you can replace it with HPP.
  • The HPP supports only active-active and implicit ALUA targets. In the HPP support table for vSphere 8.0 Update 3 and later, second level plugins and SCSI-3 persistent reservations are both listed as not supported.

So the three readings to take, in order, when a device is not where you expected it:

# 1. Is the device registered with the PSA at all?
esxcli storage core device list -d naa.6006016012345678a1b2c3d4e5f60001

# 2. Which multipathing plugins are loaded on this host?
esxcli storage core plugin list --plugin-class MP

# 3. If the Plugin field in 'core path list' said HPP, this is where it lives.
esxcli storage hpp device list -d naa.6006016012345678a1b2c3d4e5f60001
Common mistake: esxcli storage nmp device list -d on a device NMP does not own has nothing to return, and an empty result reads like a missing device rather than a wrong namespace. Check the Plugin field in esxcli storage core path list first; it names the owner, and it is the only reading that distinguishes the two.
Note: HPP uses Path Selection Schemes rather than Path Selection Plugins, and has its own verb: esxcli storage hpp device set --pss, where the scheme names are FIXED, LB-BYTES, LB-IOPS, LB-Latency, LB-RR and default rather than the VMW_PSP_* strings.

Path statistics: which path is carrying the I/O

A policy change that looks correct in esxcli storage nmp device list has not necessarily changed anything. The device can be on round robin and still be sending every command down one path, if the array is presenting only one of them as active. Path statistics are where you see the difference.

# Read and write counts, and failure counts, for every path on the host.
esxcli storage core path stats get

# Limit it to one path. The name can be the runtime name or the path UID.
esxcli storage core path stats get --path vmhba2:C0:T0:L10

The reference documents these as the SCSI stats for the paths in the system and does not say whether they reset, so take two readings a few minutes apart and compare the difference rather than trusting one absolute number. If a round robin device shows one path moving and the rest flat, read Working Paths next: the Broadcom KB states that under round robin, the paths listed there are the ones the array is presenting as active.

Note: --useANO is the option that decides whether the round robin PSP uses active, unoptimised paths. If it is set to 1, the round robin PSP includes paths in the active, unoptimized state in the round robin set. If set to 0, the PSP uses active, unoptimized paths only if no active optimized paths are available. Read it with esxcli storage nmp psp roundrobin deviceconfig get --device.
Warning: Adapter level and device level counters exist too, as esxcli storage core adapter stats get and esxcli storage core device stats get. They are three different levels of the same stack, and the reference does not state how the numbers at one level relate to the numbers at another, so compare adapter with adapter and path with path.

Do not parse the human output

The path and device list commands used on this page print a stanza format: an identifier at column zero, then indented Field: value pairs. It reads well and it parses badly, and the way it fails is quiet.

The measurements below were taken by running the one liners against the documented output shape in a POSIX shell. They are not guesses about what awk and sed would do.

One liner, applied to a field lineResult on Runtime Name: vmhba2:C0:T0:L10Result on Adapter Transport Details: WWNN: 20:00:...:11 WWPN: 10:00:...:11
awk -F: '{print $2}'vmhba2, truncated at the first colon inside the value, and with the leading space keptAlso truncated
sed 's/.*: //'vmhba2:C0:T0:L10, correct here10:00:00:00:c9:aa:11:11, silently wrong: the greedy match eats the WWNN and the WWPN label
sed -n 's/^ *Runtime Name: //p'vmhba2:C0:T0:L10, correctNot applicable, the pattern is anchored to one field name
Common mistake: The middle row is the one that costs time. sed 's/.*: //' is correct on the runtime name and wrong on the transport details line, so a script built and tested on one field produces plausible looking nonsense on another. The value it returns is a real WWPN, which is why nobody checks it.

The right answer is not a better regex. esxcli has machine readable output modes, and using one removes the whole class of problem:

# Ask esxcli for structured output instead of parsing the human form.
esxcli --formatter=csv storage core path list
esxcli --formatter=keyvalue storage core path list

The formatters, their differences and how they behave over a remote connection are covered in esxcli on ESXi: syntax, output formatters and remote execution. That is the page to read before writing any script around these commands.

Note: If you are stuck with the human form, the offset was measured rather than guessed: in the stanza shape the Broadcom KB publishes, the State line sits exactly eight lines below the Runtime Name line, so grep -i -B8 'State: dead' prints the whole stanza for each dead path.

Hidden gems

An unanchored grep in a device loop produces eighteen arguments instead of two. Broadcom’s KB on changing PSP for multiple LUNs uses a loop over esxcli storage nmp device list. The anchor in that grep is not cosmetic. Run against a two device capture, the anchored form yields two device identifiers; dropping the caret yields eighteen words, only two of which are device identifiers, because the display name line also contains the identifier and the shell splits it on whitespace:

# Correct: the caret anchors to the stanza header, which is the only line
# where the device identifier starts at column zero.
for d in $(esxcli storage nmp device list | grep '^naa\.'); do
  esxcli storage nmp device set --device "$d" --psp VMW_PSP_RR
done
anchored   '^naa\.'  ->  2 arguments:  naa....0001  naa....0002
unanchored 'naa\.'   -> 18 arguments:  naa....0001  Device  Display  Name:  DGC
                                       Fibre  Channel  Disk  (naa....0001)  ...
Common mistake: Sixteen of those eighteen would be passed to --device as device names. The same KB carries its own warning that the method is intended only for very small systems with a single array, and could be dangerous in a larger environment because it sets all selected devices to the same PSP.

The fixed policy remembers a path you explicitly chose, even after it dies. The path policy documentation draws a distinction that is easy to miss: if the host uses a default preferred path and the path’s status turns to dead, a new path is selected as preferred. But if you explicitly designate the preferred path, it will remain preferred even when it becomes inaccessible. An explicitly set preferred path is a commitment, not a hint.

Fixed on an active-passive array is a documented way to cause path thrashing. The path policy effects table states it plainly: with the fixed policy on an active-passive array, the VMkernel attempts to resume by using the preferred path, and this action can cause path thrashing or failure when another storage processor now owns the LUN. Round robin on the same array simply selects the next path in the rotation.

PolicyActive-active arrayActive-passive array
Most Recently UsedAdministrator action is required to fail back after path failureAdministrator action is required to fail back after path failure
FixedVMkernel resumes using the preferred path when connectivity is restoredVMkernel attempts to resume by using the preferred path; can cause path thrashing or failure when another SP now owns the LUN
Round RobinNo fail backNext path in round robin scheduling is selected

Unclaiming does not stick. The reference for esxcli storage core claiming unclaim says it plainly: unclaiming will not persist and periodic path claiming will reclaim these paths in the near future unless claim rules are configured to mask the path. It adds that only inactive paths with no I/O can be unclaimed, and that devices with VMFS volumes on them will typically not be unclaimable at all.


The PowerCLI equivalent

PowerCLI usually reaches these settings through vCenter rather than through a host shell, which makes it the right tool when the question spans a cluster. The names are different: esxcli uses the plugin identifiers, PowerCLI uses a four value enumeration.

esxcli PSPPowerCLI -MultipathPolicy valueMeaning
VMW_PSP_FIXEDFixedUses the preferred path whenever possible
VMW_PSP_RRRoundRobinLoad balance
VMW_PSP_MRUMostRecentlyUsedUses the most recently used path
# Every SCSI disk on one host. -LunType and -CanonicalName are both documented
# parameters of Get-ScsiLun, so filter with them rather than after the fact.
$luns = Get-VMHost esx01.lab.local | Get-ScsiLun -LunType disk

# Property names on the returned object vary by PowerCLI version, so read them
# from the object rather than assuming, before you select or filter on any.
$luns | Get-Member -MemberType Property

# The paths to one device, which is the PowerCLI form of 'core path list'.
$lun = Get-VMHost esx01.lab.local | Get-ScsiLun -CanonicalName 'naa.6006016012345678a1b2c3d4e5f60001'
Get-ScsiLunPath -ScsiLun $lun
# Collect the disk LUNs across a whole cluster, then set the policy in one call.
# The documented form passes the objects to -ScsiLun rather than through a pipe.
$luns = Get-Cluster PROD-CL01 | Get-VMHost | Get-ScsiLun -LunType disk
Set-ScsiLun -ScsiLun $luns -MultipathPolicy RoundRobin
Warning: That second block sets every disk LUN in the cluster to the same policy. Broadcom’s KB on changing PSP for multiple LUNs warns that this approach is intended only for very small systems with a single array. Set-ScsiLun -MultipathPolicy takes a four value enumeration: Fixed, MostRecentlyUsed, RoundRobin and Unknown, the last of which the reference says is supported only when connected to vCenter Server 4.1 and ESX 4.1. It therefore covers the three built in policies and nothing else. esxcli storage nmp psp list reports whatever is actually loaded on the host, which on a host with a third party plugin is a longer list.
Note: Set-ScsiLun takes -PreferredPath, and Set-ScsiLunPath takes -Active and -Preferred, which is the PowerCLI equivalent of esxcli storage core path set. The reference notes that only one path can be preferred, so making a path preferred removes the preference from the previously preferred path. The PowerCLI Command Builder assembles these pipelines without the parameter set guessing.

Where this matters

  • Planned SAN maintenance. Disabling the affected paths with core path set --state off before the fabric work starts turns a storm of failover events into a controlled drain.
  • A datastore that went read only overnight. The path states and the path stats together tell you whether the host lost paths, lost all of them briefly, or never lost any and the problem is above the storage layer.
  • A new array being brought into an existing cluster. The SATP rule search order decides which plugin claims the new LUNs, and getting that wrong is far cheaper to fix before the LUNs carry virtual machines.
  • Cluster consistency audits. One host on a different PSP from its siblings is worth catching early, and the device override described above is one way a single host drifts.
  • Post migration cleanup. After LUNs are unpresented, adapter rescan --type delete removes the dead devices that otherwise stay in every inventory report for months.
  • NVMe adoption. When the first NVMe-oF namespace appears on a host that has only ever had FC, the nmp commands stop answering for it, and the HPP namespace is where it lives.

Tips and limitations

  • These are host commands. They need a shell on the ESXi host itself, through SSH or the DCUI, with rights to run esxcli.
  • Use naa.xxx or eui.xxx device names. The documentation says explicitly not to use VML LUN names unless device names are not available, and that virtual machine HBA names are not guaranteed to be valid across reboots.
  • The host performs a periodic path evaluation every five minutes and assigns unclaimed paths to the appropriate module, so an unclaimed path can be picked back up without you doing anything.
  • core path set --state only accepts active and off. There is no command that revives a dead path.
  • nmp device set --psp takes effect immediately and permanently. nmp device set --default undoes it.
  • nmp satp set --default-psp does nothing to existing devices until a reboot or a reclaim.
  • The esxcli storage nmp commands only cover devices NMP owns, not devices claimed by HPP or by a third party plugin. Check the Plugin field in core path list.
  • A single reading of the path statistics tells you little. Take two readings a few minutes apart and compare the difference.
  • If esxcli reports a connection failure to the local host, hostd is not running and localcli is the documented substitute.
  • Script against --formatter=csv or --formatter=keyvalue, never against the human output.

Official documentation


  • PowerCLI Command Builder: builds the Get-ScsiLun and Set-ScsiLun pipelines from this page without guessing at parameter sets.

Five cheat sheets, one PDF

Subnet masks, PowerShell, Linux commands, HTTP status codes and the ESXi command line - one page each, free to keep. Leave an address and it arrives in a minute.