VFS.Error exception (VFS v0.1.0)

Copy Markdown View Source

Structured error returned by every fallible VFS.Mountable op.

Fields

  • :kind — atom from the kind/0 type. The primary control-flow value; pattern-match on this.
  • :path — the path that failed, as the user expressed it (before mount-prefix stripping). May be nil for ops that don't take a path.
  • :mount — the mountpoint that handled the op, if any. Useful for log context in mount-table dispatch.
  • :message — human-readable; defaults to a sensible string built from the other fields.

Examples

iex> {:error, err} = VFS.read_file(VFS.new(), "/nope")
iex> err.kind
:enoent

Raisable for !-style helpers:

iex> raise VFS.Error, kind: :enoent, path: "/foo"
** (VFS.Error) :enoent at /foo

Summary

Types

POSIX-style error kinds, kept tight on purpose. Pattern match on these for flow control.

t()

Functions

Build an error struct without raising. Convenience constructor for backends and the mount-table dispatcher.

Add or overwrite the :mount field on an existing error. Used by the mount-table dispatcher to attach mount context to errors bubbled up from leaf backends.

Rewrite the :path field on an existing error, regenerating the default message to match. Used by the mount-table dispatcher: backends report paths in their own namespace (mount prefix stripped), and the dispatcher rewrites them into the user's namespace — the human-readable message must follow, or logs name a path that does not exist in the user's view.

Types

kind()

@type kind() ::
  :enoent
  | :eexist
  | :eisdir
  | :enotdir
  | :erofs
  | :enotsup
  | :eacces
  | :einval
  | :exdev
  | :eio
  | :eloop

POSIX-style error kinds, kept tight on purpose. Pattern match on these for flow control.

  • :enoent — path doesn't exist
  • :eexist — path already exists (e.g. mkdir collision)
  • :eisdir — expected a file, got a directory
  • :enotdir — expected a directory, got a file
  • :erofs — the mount or wrapper is read-only
  • :enotsup — the backend doesn't support this op
  • :eacces — permission denied
  • :einval — bad argument (e.g. malformed path or option)
  • :exdev — cross-mount op that can't be atomic
  • :eio — underlying I/O failure
  • :eloop — symlink loop

t()

@type t() :: %VFS.Error{
  __exception__: true,
  kind: kind(),
  message: String.t() | nil,
  mount: String.t() | nil,
  path: String.t() | nil
}

Functions

new(kind, opts \\ [])

@spec new(
  kind(),
  keyword()
) :: t()

Build an error struct without raising. Convenience constructor for backends and the mount-table dispatcher.

put_mount(err, mount)

@spec put_mount(t(), String.t()) :: t()

Add or overwrite the :mount field on an existing error. Used by the mount-table dispatcher to attach mount context to errors bubbled up from leaf backends.

put_path(err, path)

@spec put_path(t(), String.t()) :: t()

Rewrite the :path field on an existing error, regenerating the default message to match. Used by the mount-table dispatcher: backends report paths in their own namespace (mount prefix stripped), and the dispatcher rewrites them into the user's namespace — the human-readable message must follow, or logs name a path that does not exist in the user's view.

A custom message (one the backend set explicitly) is preserved.

Examples

iex> err = VFS.Error.new(:enoent, path: "/x") |> VFS.Error.put_path("/repo/x")
iex> Exception.message(err)
":enoent at /repo/x"

iex> err = VFS.Error.new(:eio, path: "/x", message: "disk on fire")
iex> VFS.Error.put_path(err, "/repo/x").message
"disk on fire"