Error codes
fslite_core::ErrorCode is the stable, transport-independent category
for every failure an fs operation can produce. fslite-server maps
each code to an HTTP status; the CLI renders each code as the code
field of the JSON output (with --json). Custom transports should
adopt the same mapping.
The mapping is enforced by the
domain_status function (opens in a new tab)
in fslite-server/src/error.rs. The code_str table there
hand-maintains the snake_case spelling emitted in the JSON envelope.
| ErrorCode | HTTP status |
|---|---|
InvalidPathOrName | 400 Bad Request |
WorkspaceBoundaryViolation | 400 Bad Request |
InvalidCursor | 400 Bad Request |
PermissionDenied | 403 Forbidden |
NotFound | 404 Not Found |
AlreadyExists | 409 Conflict |
WrongNodeType | 409 Conflict |
DirectoryNotEmpty | 409 Conflict |
LinkLoop | 409 Conflict |
BrokenLink | 409 Conflict |
QuotaExceeded | 409 Conflict |
RevisionConflict | 412 Precondition Failed |
InvalidRange | 416 Range Not Satisfiable |
StorageBusy | 503 Service Unavailable (with Retry-After: 1) |
InternalStorageFailure | 500 Internal Server Error |
Transport-only envelopes
fslite-server adds four errors above the FileSystem layer. They
do not appear in ErrorCode — they describe a transport-level
problem rather than a domain failure.
| Variant | HTTP status |
|---|---|
ApiError::Unauthenticated | 401 Unauthorized |
ApiError::WorkspaceMismatch | 403 Forbidden |
ApiError::MalformedBody | 400 Bad Request |
ApiError::RouteNotFound | 404 Not Found |
ApiError::MethodNotAllowed | 405 Method Not Allowed |
ApiError::PayloadTooLarge | 413 Payload Too Large |
ApiError::Internal | 500 Internal Server Error |
Envelope shape
Both the domain error family and the transport error family emit the same JSON shape:
{
"code": "not_found",
"message": "not found",
"details": { "subject": "/missing.txt" }
}code is the snake_case spelling of the variant (InvalidPathOrName
→ invalid_path_or_name). message is safe to surface to end users.
details is opaque serde_json::Value with extra context — see each
code's description below.
Per-code notes
RevisionConflict—detailscarries the conflicting currentrevisionso callers can retry or surface the conflict to a user.InvalidRange—detailscarries{ "requested": "...", "available": ... }for byte ranges.QuotaExceeded—detailscarries the field that exceeded (max_bytes,max_nodes,max_file_bytes).DirectoryNotEmpty—detailsmay carry a small sample of child names for diagnostics.StorageBusy— implies transient contention (e.g., a brief SQLite write lock); theRetry-Afterheader is set to 1 second.LinkLoop/BrokenLink— only possible when symbolic links are enabled and traversed.