Skip to content

Error Codes

Reference for all Nefia structured error codes.

Nefia uses a structured error code system to help you quickly diagnose and resolve problems. Every error includes a code in the format Exxxx, where the first digit indicates the category.

PrefixCategory
E1xxxVPN
E2xxxSSH
E3xxxSFTP / Filesystem
E4xxxConfiguration
E5xxxPolicy
E6xxxAuthentication
E7xxxExecution
E8xxxTeam
E81xxSecurity / Device / Posture
E82xxSecrets / Cluster
E9xxxInternal

Using nefia explain

You can look up any error code from the terminal with the nefia explain command. This displays the title, a detailed description, step-by-step resolution instructions, and a link to the relevant documentation page.

bash
nefia explain E2001
nefia explain E2001

Error [E2001]: SSH authentication failed

The SSH key or credentials were rejected by the remote host.

Resolution:

  1. Verify the SSH key: ssh -i ~/.ssh/id_ed25519 <user>@<host>
  2. Check key file permissions: chmod 600 ~/.ssh/id_ed25519 (Linux/macOS) or use icacls to restrict access (Windows)
  3. Ensure the public key is in the remote host's ~/.ssh/authorized_keys.
  4. Re-enroll the host if SSH keys were rotated: nefia vpn reinvite --host <host>

Docs: https://www.nefia.ai/docs/errors/E2001

To list all registered error codes at once:

bash
nefia explain --list
nefia explain --list

CODE TITLE E1001 VPN connection failed E1002 VPN key invalid E1003 VPN enrollment failed E1004 VPN setup failed E1005 DERP relay connection failed E1006 DERP relay authentication failed E1007 Enrollment rate limited E2001 SSH authentication failed E2002 SSH connection failed E2003 Command timed out E2004 SSH session failed E2005 SSH host key changed E3001 File not found E3002 Permission denied E3003 File too large E3004 SFTP operation failed E3005 Path denied by policy E4001 Invalid configuration E4002 Invalid selector E4003 Host not found E5001 Command denied by policy E5002 License limit exceeded E6001 Authentication required E6002 Authentication token expired E6003 Device limit exceeded E7001 Command exited with non-zero status E7002 Invalid playbook E8001 Team not found E8002 Insufficient team permissions E8003 Team member limit exceeded E8004 Invalid invitation code E8101 Device lock denied E8102 Posture check denied E8201 Secret resolution failed E8202 Cluster node is not the leader E8301 Sudo not enabled E8302 Sudo command denied E9001 Internal error E9002 Operation cancelled E9003 Schedule not found E9004 Queue entry not found E9005 Queue invalid state E9006 Job not found


VPN Errors (E1xxx)

CodeTitleDescription
E1001VPN connection failedThe WireGuard VPN tunnel could not be established or has been disrupted.
E1002VPN key invalidThe WireGuard public or private key is malformed or does not match the peer configuration.
E1003VPN enrollment failedThe invite token was rejected, has expired, or has already been used.
E1004VPN setup failedThe WireGuard VPN interface could not be configured on the local machine.
E1005DERP relay connection failedCould not connect to the DERP relay server. The relay server may be down, the URL may be incorrect, or a firewall may be blocking WebSocket connections.
E1006DERP relay authentication failedThe DERP relay server rejected the authentication handshake. The WireGuard private key may be invalid, or the server's ACL may not include this client's public key.
E1007Enrollment rate limitedToo many enrollment requests were sent from the same IP address. The operator rate-limits enrollment to prevent abuse.
E1001 — VPN connection failed

The WireGuard VPN tunnel could not be established or has been disrupted.

StepResolution
1Check that the target host is powered on and connected to the internet.
2Verify the VPN endpoint is reachable: nefia vpn diagnose --host <host>.
3Ensure the operator and agent clocks are synchronized (WireGuard requires less than 2 minutes of skew).
4Re-enroll the host if keys may have changed: nefia vpn reinvite --host <host>.
E1002 — VPN key invalid

The WireGuard public or private key is malformed or does not match the peer configuration.

StepResolution
1Regenerate the VPN keys: nefia vpn rotate-key.
2Re-enroll the affected host: nefia vpn reinvite --host <host>.
3Check that the private key in the config is a valid base64-encoded 32-byte key.
E1003 — VPN enrollment failed

The invite token was rejected, has expired, or has already been used.

StepResolution
1Generate a new invite token: nefia vpn invite --name <host> --os <os>.
2Check that the token has not expired (default: 24 hours).
3Ensure the token has not been used by another host (tokens are single-use).
E1004 — VPN setup failed

The WireGuard VPN interface could not be configured on the local machine.

StepResolution
1Check that no other VPN or WireGuard instance is using the same listen port (default: 51820).
2Verify the VPN address range does not conflict with existing network interfaces.
3Review the VPN configuration: nefia validate.
4Check firewall rules allow UDP traffic on the WireGuard listen port.
E1005 — DERP relay connection failed

Could not connect to the DERP relay server. The relay server may be down, the URL may be incorrect, or a firewall may be blocking WebSocket connections.

StepResolution
1Verify the DERP server URL in your config: nefia validate.
2Check that the DERP server is running and reachable: curl -s https://<derp-host>/healthz.
3Ensure outbound WebSocket (wss://) connections are not blocked by a firewall or proxy.
4Run nefia vpn diagnose to test DERP connectivity.
E1006 — DERP relay authentication failed

The DERP relay server rejected the authentication handshake. The WireGuard private key may be invalid, or the server's ACL may not include this client's public key.

StepResolution
1Verify your WireGuard private key is valid: nefia vpn diagnose.
2If the DERP server uses an ACL, ensure your public key is in the allowed list.
3Re-enroll the host if keys were rotated: nefia vpn reinvite --host <host>.
4Contact the DERP server administrator if the issue persists.
E1007 — Enrollment rate limited

Too many enrollment requests were sent from the same IP address. The operator rate-limits enrollment to prevent abuse.

StepResolution
1Wait at least 30 seconds before retrying enrollment.
2If multiple agents are enrolling simultaneously, space out the requests.
3Check for retry loops in automation scripts that may be flooding the enrollment endpoint.

SSH Errors (E2xxx)

CodeTitleDescription
E2001SSH authentication failedThe SSH key or credentials were rejected by the remote host.
E2002SSH connection failedCould not establish a TCP connection to the SSH server on the remote host.
E2003Command timed outThe remote command did not complete within the configured timeout.
E2004SSH session failedAn SSH session could not be opened on an existing connection. The connection may have been dropped.
E2005SSH host key changedThe SSH host key for the remote host has changed since the last connection. This may indicate a man-in-the-middle attack or that the host was reinstalled.
E2001 — SSH authentication failed

The SSH key or credentials were rejected by the remote host.

StepResolution
1Verify the SSH key: ssh -i ~/.ssh/id_ed25519 <user>@<host>.
2Check key file permissions: chmod 600 ~/.ssh/id_ed25519 (Linux/macOS) or use icacls to restrict access (Windows).
3Ensure the public key is in the remote host's ~/.ssh/authorized_keys.
4Re-enroll the host if SSH keys were rotated: nefia vpn reinvite --host <host>.
E2002 — SSH connection failed

Could not establish a TCP connection to the SSH server on the remote host.

StepResolution
1Check that the VPN tunnel is active: nefia vpn diagnose --host <host>.
2Verify the SSH daemon is running: systemctl status sshd (Linux) or Get-Service sshd (Windows).
3Ensure the SSH port (22) is open and not blocked by a firewall.
4Increase the connect timeout if the network is slow: ssh.connect_timeout_sec in config.
E2003 — Command timed out

The remote command did not complete within the configured timeout.

StepResolution
1Increase the timeout: nefia exec --timeout 5m <command>.
2Check if the command is blocked waiting for input (avoid interactive commands).
3Verify the remote host is responsive: nefia vpn diagnose --host <host>.
E2004 — SSH session failed

An SSH session could not be opened on an existing connection. The connection may have been dropped.

StepResolution
1Retry the command; the connection pool will reconnect automatically.
2Check if the remote SSH server has a MaxSessions limit that is too low.
3Reduce concurrency if many parallel sessions are failing: --concurrency <n>.
E2005 — SSH host key changed

The SSH host key for the remote host has changed since the last connection. This may indicate a man-in-the-middle attack or that the host was reinstalled.

StepResolution
1If the host was reinstalled or its SSH keys were regenerated, remove the old entry from the known_hosts file.
2Compare the old and new fingerprints shown in the error message to verify the change is expected.
3Run nefia vpn diagnose --host <host> to check VPN and network integrity.
4If unsure, contact the administrator of the remote host before proceeding.

SFTP / Filesystem Errors (E3xxx)

CodeTitleDescription
E3001File not foundThe specified file or directory does not exist on the remote host.
E3002Permission deniedThe remote user does not have permission to access the requested file or directory.
E3003File too largeThe file exceeds the maximum allowed size for transfer.
E3004SFTP operation failedAn SFTP file operation (read, write, list, or stat) failed on the remote host.
E3005Path denied by policyThe requested file path is outside the allowed roots or matches a deny rule in the policy configuration.
E3001 — File not found

The specified file or directory does not exist on the remote host.

StepResolution
1Verify the file path is correct (paths are relative to the session root).
2List files in the directory: nefia fs list --host <host> <parent-dir>.
3Check that the path uses the correct separator for the remote OS.
E3002 — Permission denied

The remote user does not have permission to access the requested file or directory.

StepResolution
1Check file ownership and permissions on the remote host.
2Ensure the SSH user has read/write access to the target path.
3Consider using a session with a different root directory.
E3003 — File too large

The file exceeds the maximum allowed size for transfer.

StepResolution
1Use nefia fs read --out <local-path> to stream large files to disk (up to 3 GB).
2Adjust ssh.max_file_size_bytes in the configuration if appropriate.
3Consider compressing the file on the remote host before transfer.
E3004 — SFTP operation failed

An SFTP file operation (read, write, list, or stat) failed on the remote host.

StepResolution
1Retry the operation; transient SFTP errors may resolve on reconnection.
2Check that the SFTP subsystem is enabled on the remote SSH server.
3Verify disk space on the remote host if writing files.
4Review the full error with --verbose for details.
E3005 — Path denied by policy

The requested file path is outside the allowed roots or matches a deny rule in the policy configuration.

StepResolution
1Check the allowed_roots and deny_paths in your policy configuration.
2Use nefia validate to review the active policy rules.
3Open a session with the correct root: nefia session open --host <host> --root <path>.

Configuration Errors (E4xxx)

CodeTitleDescription
E4001Invalid configurationThe Nefia configuration file contains invalid or missing values.
E4002Invalid selectorThe target selector expression could not be parsed.
E4003Host not foundThe specified host ID was not found in the inventory.
E4001 — Invalid configuration

The Nefia configuration file contains invalid or missing values.

StepResolution
1Run nefia validate to see detailed validation errors.
2Re-initialize the config: nefia setup (this creates a new default config).
3Check YAML syntax for indentation errors or unquoted special characters.
E4002 — Invalid selector

The target selector expression could not be parsed.

StepResolution
1Use a valid selector format: host:<id>, group:<name>, tag:key=value, or all.
2Run nefia hosts list to see available host IDs.
3Run nefia groups list to see available group names.
E4003 — Host not found

The specified host ID was not found in the inventory.

StepResolution
1Run nefia hosts list to see available hosts.
2Check that the host ID is spelled correctly.
3If the host was recently added, reload the configuration.

Policy Errors (E5xxx)

CodeTitleDescription
E5001Command denied by policyThe command was blocked by the policy engine's deny rules.
E5002License limit exceededThe operation requires a higher license tier or exceeds the current plan's limits.
E5001 — Command denied by policy

The command was blocked by the policy engine's deny rules.

StepResolution
1Review the deny_commands list in your policy configuration.
2If the command should be allowed, add it to allow_commands or adjust the policy.
3Use nefia validate to inspect active policy rules.
E5002 — License limit exceeded

The operation requires a higher license tier or exceeds the current plan's limits.

StepResolution
1Check your current plan: nefia account.
2Upgrade your plan at nefia.ai/#pricing.
3Remove unused hosts to free up capacity: nefia hosts remove <id>.

Authentication Errors (E6xxx)

CodeTitleDescription
E6001Authentication requiredYou are not logged in. Most Nefia commands require authentication.
E6002Authentication token expiredYour login session has expired and needs to be refreshed.
E6003Device limit exceededYou have reached the maximum number of registered devices for your plan.
E6001 — Authentication required

You are not logged in. Most Nefia commands require authentication.

StepResolution
1Log in: nefia login.
2Create an account at nefia.ai/sign-up if you don't have one.
3Check if your session token file exists and is readable.
E6002 — Authentication token expired

Your login session has expired and needs to be refreshed.

StepResolution
1Log in again: nefia login.
2If this happens frequently, check your system clock is accurate.
E6003 — Device limit exceeded

You have reached the maximum number of registered devices for your plan.

StepResolution
1Remove an unused host: nefia hosts remove <id>.
2Check your current usage: nefia account.
3Upgrade your plan for more device slots: nefia.ai/#pricing.

Execution Errors (E7xxx)

CodeTitleDescription
E7001Command exited with non-zero statusThe remote command completed but returned a non-zero exit code, indicating failure.
E7002Invalid playbookThe playbook definition contains syntax errors or invalid step configurations.
E7001 — Command exited with non-zero status

The remote command completed but returned a non-zero exit code, indicating failure.

StepResolution
1Check the command's stderr output for error details.
2Run the command with --verbose to see full output.
3Verify the command syntax is correct for the remote host's shell.
E7002 — Invalid playbook

The playbook definition contains syntax errors or invalid step configurations.

StepResolution
1Validate the playbook YAML for syntax errors.
2Ensure each step has exactly one action: exec, fs_write, or fs_read.
3Check that register names use only alphanumeric characters and underscores.
4Verify when conditions reference valid registered step names.

Team Errors (E8xxx)

CodeTitleDescription
E8001Team not foundThe specified team does not exist or you do not have access to it.
E8002Insufficient team permissionsYou do not have the required role to perform this action within the team.
E8003Team member limit exceededThe team has reached the maximum number of members allowed by its plan.
E8004Invalid invitation codeThe team invitation code is invalid, expired, or has reached its maximum usage count.
E8101Device lock deniedThe device failed device-lock verification. The device's Ed25519 key does not match the registered key for this host.
E8102Posture check deniedThe device did not meet the required posture policy (e.g. OS version, disk encryption, antivirus).
E8201Secret resolution failedA secret reference could not be resolved. The secret provider may be unavailable or the secret may not exist.
E8202Cluster node is not the leaderThis operation must be performed on the Raft cluster leader node. The current node is a follower.
E8001 — Team not found

The specified team does not exist or you do not have access to it.

StepResolution
1List your teams: nefia team list.
2Check the team slug or ID for typos.
3Ask the team owner to send you an invitation if you haven't joined yet.
E8002 — Insufficient team permissions

You do not have the required role to perform this action within the team.

StepResolution
1Check your role in the team: nefia team current.
2Ask a team OWNER or ADMIN to grant you the necessary permissions.
3Some actions (e.g. removing members, creating invitations) require ADMIN or OWNER role.
E8003 — Team member limit exceeded

The team has reached the maximum number of members allowed by its plan.

StepResolution
1Remove inactive members: nefia team members, then contact an admin to remove unused accounts.
2Upgrade the team plan for more member slots: nefia.ai/#pricing.
E8004 — Invalid invitation code

The team invitation code is invalid, expired, or has reached its maximum usage count.

StepResolution
1Ask the team admin to generate a new invitation: nefia team invite.
2Check that the invitation code was copied correctly (no extra spaces).
3Invitation codes expire after the configured duration (default: 48 hours).
E8101 — Device lock denied

The device failed device-lock verification. The device's Ed25519 key does not match the registered key for this host.

StepResolution
1Re-register the device: nefia device-lock register --host <host>.
2Check that the device has not been re-imaged or cloned since registration.
3Use nefia device-lock status to inspect the current device key.
E8102 — Posture check denied

The device did not meet the required posture policy (e.g. OS version, disk encryption, antivirus).

StepResolution
1Run nefia posture check --host <host> to see which checks failed.
2Update the device to meet the required posture rules defined in your policy.
3Review posture rules in the config: nefia validate.
E8201 — Secret resolution failed

A secret reference could not be resolved. The secret provider may be unavailable or the secret may not exist.

StepResolution
1Check that the secret exists in the configured provider: nefia secrets list.
2Verify the secret provider is reachable (e.g. Vault server, AWS credentials).
3Review the secret reference syntax in your config or playbook.
E8202 — Cluster node is not the leader

This operation must be performed on the Raft cluster leader node. The current node is a follower.

StepResolution
1Run nefia cluster status to identify the current leader node.
2Retry the command on the leader node, or wait for a leader election to complete.
3If the cluster has no leader, check that a quorum of nodes is reachable.

Internal Errors (E9xxx)

CodeTitleDescription
E9001Internal errorAn unexpected internal error occurred. This is likely a bug.
E9002Operation cancelledThe operation was cancelled, either by the user (Ctrl+C) or a timeout.
E9001 — Internal error

An unexpected internal error occurred. This is likely a bug.

StepResolution
1Retry the operation.
2Run with --debug for detailed error information.
3Report the issue at github.com/co-r-e/nefia-cli/issues with the debug output.
E9002 — Operation cancelled

The operation was cancelled, either by the user (Ctrl+C) or a timeout.

StepResolution
1Retry the operation if it was interrupted unintentionally.
2Increase the timeout if the operation needs more time: --timeout <duration>.

Domain Code Mapping

The following table maps domain-specific error codes (used in JSON output and MCP responses) to their corresponding E-codes.

Domain CodeE-CodeCategory
VPN_FAILEDE1001VPN
VPN_SETUP_FAILEDE1004VPN
DERP_CONNECT_FAILEDE1005VPN
DERP_AUTH_FAILEDE1006VPN
ENROLLMENT_RATE_LIMITEDE1007VPN
SSH_AUTH_FAILEDE2001SSH
SSH_CONNECT_FAILEDE2002SSH
CMD_TIMEOUTE2003SSH
SSH_SESSION_FAILEDE2004SSH
SSH_HOST_KEY_CHANGEDE2005SSH
FILE_NOT_FOUNDE3001Filesystem
PERMISSION_DENIEDE3002Filesystem
FILE_TOO_LARGEE3003Filesystem
SFTP_FAILEDE3004Filesystem
PATH_DENIEDE3005Filesystem
CONFIG_INVALIDE4001Configuration
SELECTOR_INVALIDE4002Configuration
HOST_NOT_FOUNDE4003Configuration
POLICY_DENIEDE5001Policy
LICENSE_DENIEDE5002Policy
AUTH_REQUIREDE6001Authentication
AUTH_EXPIREDE6002Authentication
DEVICE_LIMIT_EXCEEDEDE6003Authentication
CMD_EXIT_NONZEROE7001Execution
PLAYBOOK_INVALIDE7002Execution
TEAM_NOT_FOUNDE8001Team
TEAM_ACCESS_DENIEDE8002Team
TEAM_MEMBER_LIMITE8003Team
TEAM_INVITE_INVALIDE8004Team
DEVICE_LOCK_DENIEDE8101Security
POSTURE_DENIEDE8102Security
SECRET_RESOLVE_FAILEDE8201Secrets
CLUSTER_NOT_LEADERE8202Cluster
SESSION_NOT_FOUNDE9001Internal
INTERNALE9001Internal
CANCELLEDE9002Internal
SUDO_DISABLEDMCP
SUDO_DENIEDE5001Policy
JIT_REQUIREDMCP
VPN_NOT_READYE1001VPN
SCHEDULE_NOT_FOUNDMCP
QUEUE_ENTRY_NOT_FOUNDMCP
QUEUE_INVALID_STATEMCP
JOB_NOT_FOUNDMCP
CONCURRENCY_LIMITMCP
RATE_LIMITEDMCP
AUTH_REQUIREDMCP
SERVICE_DEPLOY_FAILEDMCP
CONFIG_APPLY_FAILEDMCP
BASELINE_DRIFTMCP
MOUNT_FAILEDMCP
CONTAINER_FAILEDMCP
CLUSTER_JOIN_FAILEDMCP
SSHCA_SIGNING_FAILEDMCP
STREAM_TIMEOUTMCP
FEATURE_DISABLEDMCP
METHOD_NOT_FOUNDMCP

MCP-Specific Error Codes

The MCP server uses additional JSON-RPC error codes that are specific to the MCP protocol. These codes appear in the error.code field of JSON-RPC error responses, not in the Exxxx format.

RPC CodeDomain CodeDescriptionTransient
-32001POLICY_DENIEDOperation blocked by policy engineNo
-32002PATH_DENIEDPath outside session root (sandbox escape)No
-32003SSH_AUTH_FAILEDSSH authentication failedNo
-32004SSH_CONNECT_FAILEDSSH connection failedYes
-32005CMD_TIMEOUTCommand exceeded timeoutYes
-32006SFTP_FAILEDSFTP operation failed (also covers FILE_NOT_FOUND, PERMISSION_DENIED, FILE_TOO_LARGE)Conditional
-32007SESSION_NOT_FOUNDSession ID does not exist or expiredNo
-32008HOST_NOT_FOUNDHost ID not found in configurationNo
-32009VPN_FAILEDVPN tunnel operation failedYes
-32010SESSION_REQUIREDSession required but not providedNo
-32011PLAYBOOK_FAILEDPlaybook definition invalid or execution failedNo
-32012COMMAND_FAILEDCommand returned non-zero exit codeNo
-32013ACCESS_DENIEDAuthentication, licensing, or permission errorNo
-32014CANCELLEDOperation cancelled or timed outNo
-32015DEVICE_LOCK_DENIEDDevice-lock verification failedNo
-32016POSTURE_DENIEDDevice posture check failedNo
-32017SECRET_RESOLVE_FAILEDSecret reference could not be resolvedNo
-32018CLUSTER_NOT_LEADEROperation must run on Raft cluster leaderNo
-32019SERVER_NOT_INITIALIZEDMCP client has not sent initialize handshakeNo
-32020SUDO_DISABLEDSudo not enabled in configurationNo
-32021SUDO_DENIEDSudo command denied by policyNo
-32022JIT_REQUIREDJust-In-Time access requiredNo
-32023VPN_NOT_READYVPN tunnel not yet establishedYes
-32024SCHEDULE_NOT_FOUNDSchedule not foundNo
-32025QUEUE_ENTRY_NOT_FOUNDQueue entry not foundNo
-32026QUEUE_INVALID_STATEQueue entry in invalid stateNo
-32027JOB_NOT_FOUNDJob ID not foundNo
-32028CONCURRENCY_LIMITAll dispatch slots in useYes
-32029RATE_LIMITEDRate limit exceededYes
-32030AUTH_REQUIREDAuthentication required for team/auth operationNo
-32031SERVICE_DEPLOY_FAILEDService deploy composite operation failedNo
-32032CONFIG_APPLY_FAILEDConfig apply composite operation failedNo
-32033BASELINE_DRIFTSystem baseline comparison detected driftNo
-32034MOUNT_FAILEDMount or unmount operation failedNo
-32035CONTAINER_FAILEDContainer operation failedNo
-32036CLUSTER_JOIN_FAILEDFailed to add peer to Raft clusterYes
-32037SSHCA_SIGNING_FAILEDSSH CA certificate signing failedNo
-32038STREAM_TIMEOUTFile streaming operation timed outYes
-32039FEATURE_DISABLEDFeature not enabled in nefia.yamlNo
-32601METHOD_NOT_FOUNDTool or method not foundNo

Transient errors include a retry_after_ms field in the response. AI agents should wait for the specified duration before retrying. Non-transient errors require a different approach (e.g., fixing configuration, using a different host, or requesting JIT access).

Each MCP error response also includes a recovery_tool field that suggests which MCP tool to call for resolution:

Error CodeRecovery ToolDescription
HOST_NOT_FOUNDnefia.hosts.listList available hosts to find the correct ID
SESSION_NOT_FOUNDnefia.session.openOpen a new session
SESSION_REQUIREDnefia.session.openOpen a session first
POLICY_DENIEDnefia.policy.testPre-check policy before retrying
SSH_AUTH_FAILEDnefia.vpn.diagnoseDiagnose connectivity
SSH_CONNECT_FAILEDnefia.vpn.diagnoseDiagnose connectivity
VPN_FAILEDnefia.vpn.diagnoseDiagnose VPN issues
VPN_NOT_READYnefia.vpn.diagnoseWait and diagnose
SFTP_FAILEDnefia.vpn.diagnoseCheck connectivity
POSTURE_DENIEDnefia.posture.checkCheck posture compliance
JIT_REQUIREDnefia.jit.requestRequest temporary access
SCHEDULE_NOT_FOUNDnefia.schedule.listList available schedules
QUEUE_ENTRY_NOT_FOUNDnefia.queue.listList queue entries
PATH_DENIEDnefia.policy.testTest path against policy
CMD_TIMEOUTnefia.sys.processesCheck running processes
PLAYBOOK_FAILEDnefia.playbook.validateValidate playbook definition
COMMAND_FAILEDnefia.sys.logsCheck system logs
ACCESS_DENIEDnefia.jit.requestRequest elevated access
DEVICE_LOCK_DENIEDnefia.device_lock.statusCheck device lock status
SECRET_RESOLVE_FAILEDnefia.secrets.testTest secret provider
CLUSTER_NOT_LEADERnefia.statusCheck cluster status
QUEUE_INVALID_STATEnefia.queue.listList queue entries
JOB_NOT_FOUNDnefia.statusCheck system status
CANCELLEDnefia.statusCheck system status
INVALID_PARAMSnefia.tools.schemaGet tool parameter schema
RATE_LIMITEDnefia.statusCheck system status
SERVER_NOT_INITIALIZEDnefia.statusCheck server status
CONCURRENCY_LIMITnefia.statusCheck system status
SERVICE_DEPLOY_FAILEDnefia.service.deployRetry service deployment
CONFIG_APPLY_FAILEDnefia.config.applyRetry config application
BASELINE_DRIFTnefia.system.baselineRe-run baseline comparison
MOUNT_FAILEDnefia.sys.mount.listCheck mount status
CONTAINER_FAILEDnefia.container.listCheck container status
CLUSTER_JOIN_FAILEDnefia.cluster.statusCheck cluster status
SSHCA_SIGNING_FAILEDnefia.sshca.statusCheck SSH CA status
STREAM_TIMEOUTnefia.fs.statCheck file status
FEATURE_DISABLEDnefia.config.showCheck which features are enabled
METHOD_NOT_FOUNDnefia.tools.schemaGet available tool schema

Error System Architecture

Nefia's error system is composed of two layers: type-safe sentinel errors and structured error codes.

Sentinel Errors and errors.Is()

All domain errors are defined as sentinel error variables in the pkg/types package. By using the types.Errorf helper to wrap a sentinel with %w, matching via errors.Is() works correctly.

go
// Sentinel error definition (pkg/types/types.go)
var ErrVPNFailed = errors.New("VPN_FAILED")
 
// Creating an error — wrap the sentinel using types.Errorf
err := types.Errorf(types.ErrVPNFailed, "tunnel setup: %w", innerErr)
 
// Checking an error — match against the sentinel with errors.Is()
if errors.Is(err, types.ErrVPNFailed) {
    // Handle as a VPN_FAILED category error
}

Internally, types.Errorf is implemented as fmt.Errorf("%w: "+format, sentinel, args...), making it fully compatible with the standard Go errors.Is() / errors.As() unwrap chain. Multiple sentinels can also be chained together.

FormatStructured — User-Facing Error Display

errcodes.FormatStructured(err, verbose) matches an error against the registered error code entries and produces a structured, user-facing message.

  • Verbose mode (--verbose): Displays the error code, title, detailed description, all resolution steps, and a documentation link.
  • Brief mode (default): Displays only the error code, title, and the first resolution step.

Matching is performed in two stages:

  1. Fast path — Attempts to match against sentinel errors using errors.Is() (O(1) lookup).
  2. Fallback — Scans the error message string for a domain code (e.g., "VPN_FAILED") for backward compatibility.

SentinelFor — Reverse Lookup from Domain Code to Sentinel

errcodes.SentinelFor(code) retrieves the corresponding sentinel error variable from a domain code string (e.g., "SSH_AUTH_FAILED") in O(1) time. This is used when the MCP server or external tools receive a string-based error code and need to convert it into a sentinel that can be compared using errors.Is().

go
sentinel, ok := errcodes.SentinelFor("SSH_AUTH_FAILED")
if ok && errors.Is(err, sentinel) {
    // Handle as an SSH authentication error
}

MCP Error Classification

The MCP server (internal/mcp) uses only errors.Is() to classify domain errors into JSON-RPC error codes. It does not use the string-matching fallback.

go
// internal/mcp/mcp.go — domainErrorToRPCCode()
func domainErrorToRPCCode(err error) int {
    switch {
    case errors.Is(err, types.ErrPolicyDenied):
        return codePolicyDenied
    case errors.Is(err, types.ErrSSHAuthFailed):
        return codeSSHAuthFailed
    // ...
    }
}
Exit Codes

Numeric exit codes returned by the CLI and their meanings.

CLI Commands

Complete reference for all Nefia CLI commands, flags, and options.