Every error the library returns carries one filesystem.Code from a closed set of twelve. This page lists each code with its sentinel, its meaning, the HTTP status fshttp.StatusOf gives it, what produces it in each package and backend, and how each HTTP handler shows it to clients. It is generated from reading errors.go, fshttp/fshttp.go and every package that returns a code. For how to handle errors in application code, read Errors first.
| Code | Constant | Sentinel | Meaning | fshttp.StatusOf |
Retried by layer.Retry |
|---|---|---|---|---|---|
not_found |
CodeNotFound |
ErrNotFound |
the key, disk, file, attachment, upload ID or other named thing does not exist | 404 | no |
exists |
CodeExists |
ErrExists |
a conditional write found the key, or a name is already taken | 409 | no |
invalid_key |
CodeInvalidKey |
ErrInvalidKey |
the key is empty, longer than 1,024 bytes, not UTF-8, has a control character or a .. segment, or is reserved by a driver |
400 | no |
invalid_argument |
CodeInvalidArgument |
ErrInvalidArgument |
an option, argument, DSN or request is invalid | 400 | no |
unsupported |
CodeUnsupported |
ErrUnsupported |
the backend lacks the capability and there is no portable fallback | 501 | no |
read_only |
CodeReadOnly |
ErrReadOnly |
a mutation reached a read-only disk | 403 | no |
too_large |
CodeTooLarge |
ErrTooLarge |
a body passed its size limit; nothing is stored | 413 | no |
rejected |
CodeRejected |
ErrRejected |
a policy refused the content; nothing is stored | 415 | no |
quota_exceeded |
CodeQuotaExceeded |
ErrQuotaExceeded |
the scope has no storage left | 507 | no |
permission |
CodePermission |
ErrPermission |
the backend, a guard, a hook or a signature refused the operation | 403 | no |
unavailable |
CodeUnavailable |
ErrUnavailable |
a transient failure: throttling, a timeout, a dropped connection, a service that is down | 503 | yes, when the operation is replayable |
conflict |
CodeConflict |
ErrConflict |
the operation was refused by the state the object or record is in now: it changed since it was read, or its state forbids the operation | 409 | no |
not_modified |
CodeNotModified |
ErrNotModified |
a conditional read found the object unchanged, so no body is returned; not a failure | 304 | no |
unknown |
CodeUnknown |
ErrUnknown |
the error could not be classified | 500 | no |
filesystem.CodeValues lists them in this order. fshttp.StatusOf(nil) is 200. A driver maps every native error into one of these; an error it cannot classify becomes unknown, never a new code.
*filesystem.Error is the one error type the library returns:
| Field | Holds |
|---|---|
Code |
the code |
Op |
the operation kind (write, stat, …; operations), empty outside a Disk operation |
Disk |
the disk's name |
Key |
the key, the directory of a list, or the source of a copy or move |
Err |
the cause, which may be the backend's native error; errors.As reaches it through Unwrap |
Error() renders filesystem: <op> <disk>:<key>: <code>: <cause>, leaving out the parts that are empty: filesystem: stat media:reports/missing.txt: not_found: no object "reports/missing.txt".
Rules the functions follow:
errors.Is(err, filesystem.ErrNotFound)is true for every*Errorwith that code anywhere in the chain, whatever its operation, disk or key.filesystem.CodeOf(err)is the code of the outermost*Errorin the chain (anunknownone wrapping a context error reads asunavailable), the code of a bare sentinel,not_found,existsorpermissionfor theio/fssentinels,unavailableforcontext.Canceledandcontext.DeadlineExceeded,unknownfor any other non-nil error, and""for nil. Wrapping a coded error infmt.Errorf("…: %w", err)keeps its code.- When a driver returns an error that is not a
*Error, the Disk classifies it:fs.ErrNotExistbecomesnot_found,fs.ErrExistexists,fs.ErrPermissionpermission, anything elseunknown. The original stays the cause. filesystem.NewError(code, cause)andfilesystem.Errorf(code, format, args…)are how drivers, interceptors and plugins build coded errors.*filesystem.BatchErrorreports the keys aDeleteKeyscould not delete:Failuresis a list ofKeyError{Key, Err}, every other key was deleted, anderrors.IsandCodeOfsee the per-key errors (errors.Is(err, ErrPermission)asks whether any key failed for lack of permission).
- Disk:
Stat,Read,ReadRange,ReadAll,CopyandMoveof a missing key;SetVisibilityof a missing key; multipart calls with an unknown upload ID.Existsturns it intofalse, nil.Deleteof a missing key is not an error. - Manager:
Disk(name)for an unregistered name,Default()with no disks,SetDefaultof an unknown name. - Drivers: S3
NoSuchKey,NotFound(a HEAD 404),NoSuchUploadand any 404; GCSErrObjectNotExist,ErrBucketNotExistand 404; AzureBlobNotFound,ContainerNotFoundand 404; local and SFTP a missing file, a path through a file (not a directory) and a key that is a directory; memory a missing key. - upload:
FromURLwhen the remote server answers 404 or 410. - records: a file, attachment, folder, version, variant or share link that does not exist in the scope, and a file in the trash where a live one is needed (
file "…" is in the trash);quota.Usageof a scope with no usage row. - share: a link token that is unknown, expired or used up (
link not found or no longer valid), deliberately the same answer for all three.
- Disk:
WritewithIfNotExistswhen the key exists (S3PreconditionFailedand 412, GCS 412, AzureConditionNotMet,BlobAlreadyExists, 409 and 412, local and SFTP an existing file, memory). - Mux and Manager:
Registerof a scheme twice,Addof a disk name twice. - records:
Attachof a file already attached to the owner under the role;Attachto an occupied single role (useSetAttachment); a plugin installed twice; folders: a sibling with the same name.
- Disk: every method, before the driver or any interceptor runs, through
filesystem.CleanKey: empty after cleaning, more thanMaxKeyLength(1,024) bytes, invalid UTF-8, a control character (NUL included), a..segment. - Drivers: keys under a driver's reserved directory:
.filesystemon local and SFTP (staging for atomic writes),.filesystem-multiparton Azure (multipart markers).
- Disk construction: an invalid disk name (
[A-Za-z0-9][A-Za-z0-9._-]{0,63}), a nil driver, a driver that declares a capability it does not implement orPresignPartwithoutMultipart, a nil interceptor, a nil URL signer, a public URL that is not absolutehttp(s), an unknown default visibility. - Disk calls: a nil body, a negative
MaxSize,SizeHint, byte range or list limit, an unknown visibility, header values with CR or LF, a copy or move onto the same key,DeletePrefixof the root, a presign method other than GET or PUT, an expiry not in (0, 7 days], a part number outside 1 to 10,000, an empty upload ID, a completion with no parts, a retry of a write whose body is a one-shot stream. - Configuration: a DSN that does not parse, a scheme with no opener, an unknown DSN parameter, a non-boolean or non-numeric value, a missing bucket, container, path, user or authentication, a password inside an SFTP DSN,
OpenManagerwith no disks, an unset…_DSNvariable, two disks reading one variable, a default disk not in the list; the error names the variable or parameter, never the DSN. - signedurl: a base URL that is not absolute or has a query, no keys, a key shorter than 32 bytes, an empty or repeated key ID.
- upload: a policy without
MaxSizeor allowed types, with an unknown visibility or a malformed extension; a request that is not multipart, has more files than allowed or no file in the field; a ticket request that is not valid JSON or not POSTed; Uppy bodies that are not JSON, a missingkeyparameter, a part number that is not a number;FromURLof a non-HTTP URL, a URL with credentials, a private or loopback address, too many redirects, a 4xx answer other than 404, 410 and 429. - upload sessions: a
SessionRequestthat would widen the policy (aMaxSizeabove it or below itsMinSize, a type outside itsAllowed), with neither or both ofKeyandPrefix, a malformed type pattern, more thanMaxSessionTypestypes, or a TTL outside (0,MaxSessionLifetime]. - records quarantine: a quarantined file recorded or made public, or a public file quarantined (
ErrPublicQuarantine); an unknownScanFailure;QuarantineContenton a change other than a replacement. - records and plugins: an unregistered owner type, an owner ID or role of the wrong shape, an unknown
Previousor visibility, a reorder that does not list each attachment once, an invalid cursor or page size, a migration edited after it ran, an invalid plugin name or a migration owned by another plugin; plugin-specific limits (tags: length and count; folders: names, depth, moving into itself, deleting a non-empty folder; versions: keeping fewer than one; share: lifetime and download count). - Drivers: a local key whose parent path is a file; an S3 or Azure multipart completion whose parts are missing, out of order or carry the wrong ETag (S3
InvalidPart,InvalidPartOrder,EntityTooSmall). - contrib: an imaging transform with an unknown mode, format or gravity, a size outside 1 to 8,192, a quality outside 0 to 100; tus without
Disk,TempDirorBasePath; variants without transforms or with an undeclared name.
- Disk: a method whose capability is missing and has no fallback:
SetVisibility,SignedURL(noPresignand no signer),PublicURL(noPublicURLand no configured base), the multipart methods; a write withMetadata,HeadersorIfNotExiststhe driver cannot store or honour; a write whose visibility differs from the default on a driver without per-object visibility. - Mirror: a signed PUT or presigned part on a mirrored disk (it would bypass the mirrors).
- Drivers: S3
CreateMultipartwithIfNotExists; an SFTP server without theposix-renameextension. - upload: every
Uppyroute on a disk withoutMultipartandPresignPart. - records: an engine other than SQLite, Postgres and MySQL.
filesystem.ReadOnly()and the DSN parameterreadonly=true: every operation withOp.Mutating, including a signed PUT URL.Disk.Checkon a read-only disk reports it, because the check writes.
- Disk: a body that passes
WriteOptions.MaxSizewhile streaming, or aSizeHintabove it; nothing larger is stored. - upload: a file over
Policy.MaxSize(form, import, tus,Receive), a request over the form cap, a ticket whose declared size is outside (0,MaxSize], a directly uploaded object larger than the policy atConfirm, a remote file that announces a size over the limit. - fshttp: a signed PUT over
SignedOptions.MaxUploadBytes(5 GiB by default). - scan: a file larger than clamd's
StreamMaxLength. - imaging: an input over
Options.MaxBytes.
- upload: a detected content type not in
Policy.Allowedor inPolicy.Deniedand the default denied list (HTML, SVG, XML, JavaScript, executables); a file name with a denied extension in any dotted segment (photo.php.jpg); an extension outsidePolicy.Extensions; withMatchExtension, a name whose extension claims another type than the bytes; a refusal fromPolicy.ProcessorPolicy.Inspect. - scan: an infected file (
scan: the file is infected (<signature>)). - upload sessions: a session whose types the endpoint's policy no longer allows (
the upload session's types are no longer allowed). - imaging: a file that is not a supported image, an image over the pixel limit, a crop outside the image; variants of a file that is not an image.
- records/quota: an upload or replacement that would take the scope past its byte or file limit, refused inside the upload's transaction.
- Drivers: S3
AccessDeniedand 403; GCS and Azure 401 and 403; local and SFTP file modes (fs.ErrPermission); SFTP authentication failure at open. - signedurl and fshttp: a missing or bad signature, a wrong method, an unknown key ID, an expired link: one answer for all (
signed URL is invalid or expired). - layer.Guard: any refusal without a code of its own.
- recordshttp: a refusal by the
Scopehook (answered 401) or theAuthorizehook (403); Uppy: a refusal byUppyOptions.Authorize(403). - upload sessions: a missing, malformed, unknown, revoked or expired
Upload-Sessiontoken, or a wrong secret: one answer for all (upload session is missing, unknown or expired, 403).
- Drivers: S3
SlowDown, 429 and 5xx; GCS and Azure 429 and 5xx; an SFTP server that cannot be dialled (also when a dropped connection is redialled), and an SFTP connection lost during an operation (the next call reconnects when the disk has a dialer, as every disk opened from a DSN does; a disk built from aClientalone staysunavailableuntil reopened). An S3, GCS or Azure answer that carriedRetry-Afterkeeps it on the error (filesystem.RetryAfterOf), solayer.Retrywaits at least that long andfshttppasses it on. - Any operation: a context that ended, by deadline or cancellation, including an attempt cut short by
layer.Timeout;layer.Retryretries it only while the caller's own context is alive. - layer.Limit: a caller whose context ends while waiting for a slot.
- Mirror: a mirror that failed after the primary succeeded (the object exists on the primary only; retrying converges).
- scan: clamd unreachable, an unexpected reply or an error reply; any scanner error without a code of its own.
- upload:
FromURLnetwork failures, remote 5xx answers and a remote 429 (too many requests). - records: another process holding the MySQL migration lock past
WithMigrationLockWait; quota's counter row racing on first insert.
Read the object or record again and decide; a blind retry meets the same state.
- Compare-and-swap writes (
WriteOptions.IfMatch): the object changed, or is gone, since the caller read its ETag (memory, local, S3, GCS, Azure, sqlblob, Dropbox, OneDrive, Vercel Blob). Nothing is written. - Object state: a read of an S3 or Azure object in an archive tier that is not restored (
s3.ErrArchived,azure.ErrArchived); an Azure append to a blob that is not an append blob; a GCS storage-class change that raced; a Google Drive key naming two or more files. - Disk:
ErrSuperseded, a concurrent attempt that already delivered the result;Synconto a case-insensitive disk where two source keys collide. - upload: a chunked upload taken over by another request (
another request took over assembling this upload); a request whoseIdempotency-Keytwin is still running; content addressing that finds identical content stored with other visibility or headers. - records:
ErrChanged, a change refused byIfUnchanged(recordshttp answers it 412, as a failedIf-Match);SetVisibilityin place on a file that shares its object with others;ErrQuarantined, a link, view, share, stream or public visibility asked for a quarantined file, orSetStatusasked to move one out of quarantine (recordshttp answers 409; share links answer the uniform 404);ErrNotQuarantined,FailScanfor a file that is not quarantined. - records plugins: locks:
ErrLocked, a change to a file checked out by someone else; audit:ErrChainBroken, a hash chain that does not verify. - contrib: archive: an object that changed while it was read; crypt: a key rotation that met a concurrent write.
- Disk.ReadIf (and the cache disk):
IfNoneMatchmatched or the object was not modified sinceIfModifiedSince.fshttpanswers 304.
- Any driver error the driver does not classify. A context deadline or cancellation is not here: it is
unavailable(see above), anderrors.Is(err, context.Canceled)andcontext.DeadlineExceededstill work on the cause. Disk.Checkreading back different bytes than it wrote.- An Azure server-side copy that ends in a failed state.
- folders: a subtree deeper than the limit or a cycle found in stored data.
| Handler | Status | Body |
|---|---|---|
fshttp.Signed, fshttp.Public |
StatusOf(err); every signature failure is 403 |
the status text only; a private and a missing key both answer 404 on Public |
upload.Handler, PresignHandler, Uppy |
StatusOf(err) |
{"error": "…", "code": "<code>"}; the message is the error's own for too_large, rejected, quota_exceeded, invalid_argument and invalid_key, the status text for every other code |
upload.Handler with Partial |
200 when some files were stored, else the first failure's status | {"files": […], "failed": [{"filename", "error", "code"}]} |
recordshttp.Handler |
StatusOf(err), 401 for Scope, 403 for Authorize, 413 for the request cap |
{"error": "…", "code": "<code>"}; client-visible messages as for upload, plus exists |
contrib/tus |
StatusOf(err) on the final PATCH (including an OnStored error); 415 for a refused declared type, 403 for Authorize (on any request), 400 for a deferred length, 413 for a declared length over MaxSize (from tusd) |
ERR_<CODE>: <message> in tusd's plain-text format, the message shown for the same client-visible codes |
Driver messages, keys of other objects and hook errors never reach a client through these handlers.
Each of these shapes is a default. An fshttp.ErrorWriter in the handler's options (Errors on fshttp.PublicOptions, SignedOptions, ZipOptions and on every upload handler's options, Responder{Errors} in the framework adapters) renders the error instead, in any envelope and with any status; see Your own error envelope.
Note on tus: an OnStored error keeps its code, as in upload.Handler: a quota_exceeded from a records upload in OnStored reaches a tus client as 507, and an error with no code as 500.
- Errors: handling errors in application code.
- Troubleshooting: the error messages you are most likely to meet, and their fixes.
- Operations and events: the
Opan error names.