siftp

Error codes

Every failure carries {code, message, hint, docs_url}. Branch on code. Codes are never renamed or reused; new ones may be added, so treat an unknown code as internal.

CodeHTTPFTPSFTP statusMeaning
auth_failed401530auth refusedMissing or wrong credentials
permission_denied403550PERMISSION_DENIED (3)Logged in, but not allowed
not_found404550NO_SUCH_FILE (2)No such file, directory, user, or session
already_exists409550FAILURE (4)The name is taken
invalid_path400553PERMISSION_DENIED (3)The path leaves the root or is malformed
invalid_command400500BAD_MESSAGE (5)Malformed command, packet, body, or config
rate_limited429421FAILURE (4)A limit fired: ban, cap, timeout, drain
quota_exceeded507552FAILURE (4)The write would exceed the user's quota
tls_required426534n/aTLS is required for this
internal500451FAILURE (4)Server-side fault

FTP may use a protocol-specific number where an RFC requires one (for example 504 for an unknown HOST, 503 for HOST after USER); the code after the number is always one of the ten.

auth_failed

Credentials were missing or wrong, the password expired, the key is expired or revoked, the user may not log in under this FTP HOST, or (admin API, MCP) the token is wrong or not configured. All of these look the same on purpose. Repeated failures from one address lead to a ban (rate_limited).

permission_denied

The user lacks the permission bit for this path (r w d n m l), possibly because of a directory rule; a config-file user was changed through the API (edit the file instead); a WebDAV client tried to write (the gateway is read-only); or an active-mode PORT named another host or a port below 1024. The hint says which bit is missing.

not_found

The file, directory, user, or session does not exist. List the parent (MLSD, SFTP READDIR, GET /api/v1/files) or the collection (GET /api/v1/users, GET /api/v1/sessions).

already_exists

A create collided with an existing name: MKD, an exclusive SFTP open, SFTP RENAME onto an existing file (use posix-rename@openssh.com to replace), or a user name that is taken.

invalid_path

The path contains NUL, a .. that leaves the root (also when percent-encoded), a symlink that points outside, or a new symlink whose target is outside the root. The same request is refused identically on every protocol.

invalid_command

The request is malformed: unknown FTP verb, bad argument, oversized line or packet, unsupported SFTP extension, invalid JSON, unknown config key, weak password hash, unsupported SSH key option. The hint names the expected form; HELP, tools/list, and /api/v1/openapi.json list what is valid.

rate_limited

A protective limit fired: login ban, connection cap (global or per address), per-user session cap, too many open SFTP handles, too many concurrent admin requests, an idle or handshake timeout, or the server is draining for a restart. Wait and retry; operators tune these under [server].

quota_exceeded

The write (upload, SFTP write, or SETSTAT that grows a file) would exceed quota_bytes. The partial file is removed unless the client was extending an existing one (REST, APPE). Free space or raise the quota.

tls_required

The server requires TLS (require_tls), PROT was sent without AUTH TLS, CCC was attempted, active mode was combined with PROT P, or a TLS data connection did not resume the control session while require_session_reuse is on. Connect with AUTH TLS, PBSZ 0, PROT P, or use the implicit FTPS port.

internal

A server-side fault: disk error, unreadable TLS material, an S3 or LDAP server that is down or refusing access. Retry once; if it persists, the message and the daemon log name the cause.