Skip to content

Error Types

envpkt uses discriminated union types for errors. Each error has a _tag field for pattern matching.

Errors from loading and parsing envpkt.toml.

type ConfigError =
| { readonly _tag: "FileNotFound"; readonly path: string }
| { readonly _tag: "ParseError"; readonly message: string }
| { readonly _tag: "ValidationError"; readonly errors: List<string> }
| { readonly _tag: "ReadError"; readonly message: string }

| Tag | When | | ----------------- | ---------------------------------------------- | | FileNotFound | The specified config file does not exist | | ParseError | TOML syntax error | | ValidationError | Schema validation failed (with list of errors) | | ReadError | File system read error |

Errors from catalog resolution.

type CatalogError =
| { readonly _tag: "CatalogNotFound"; readonly path: string }
| { readonly _tag: "CatalogLoadError"; readonly message: string }
| { readonly _tag: "SecretNotInCatalog"; readonly key: string; readonly catalogPath: string }
| { readonly _tag: "MissingSecretsList"; readonly message: string }

| Tag | When | | -------------------- | --------------------------------------------- | | CatalogNotFound | The catalog file path does not exist | | CatalogLoadError | Catalog file failed to load or parse | | SecretNotInCatalog | Agent references a key not defined in catalog | | MissingSecretsList | Agent uses catalog but has no secrets array |

Errors from fnox integration.

type FnoxError =
| { readonly _tag: "FnoxNotFound"; readonly message: string }
| { readonly _tag: "FnoxCliError"; readonly message: string }
| { readonly _tag: "FnoxParseError"; readonly message: string }

| Tag | When | | ---------------- | ------------------------------- | | FnoxNotFound | fnox CLI or config not found | | FnoxCliError | fnox command execution failed | | FnoxParseError | fnox output could not be parsed |

Errors from agent identity operations.

type IdentityError =
| { readonly _tag: "AgeNotFound"; readonly message: string }
| { readonly _tag: "DecryptFailed"; readonly message: string }
| { readonly _tag: "IdentityNotFound"; readonly path: string }

| Tag | When | | ------------------ | --------------------------------------------- | | AgeNotFound | age encryption tool not installed | | DecryptFailed | Agent key decryption failed | | IdentityNotFound | Identity key file not found at specified path |

Errors from key generation and config update operations.

type KeygenError =
| { readonly _tag: "AgeNotFound"; readonly message: string }
| { readonly _tag: "KeygenFailed"; readonly message: string }
| { readonly _tag: "KeyExists"; readonly path: string }
| { readonly _tag: "WriteError"; readonly message: string }
| { readonly _tag: "ConfigUpdateError"; readonly message: string }

| Tag | When | | ------------------- | ------------------------------------------------------- | | AgeNotFound | age-keygen CLI not found on PATH | | KeygenFailed | age-keygen command failed or output unreadable | | KeyExists | Identity file already exists (use --force) | | WriteError | Failed to write identity file or create directory | | ConfigUpdateError | Failed to read/write envpkt.toml for recipient update |

Errors from validating from_key alias references in envpkt.toml. Raised at config load time before any secret resolution begins.

type AliasError =
| {
readonly _tag: "AliasInvalidSyntax"
readonly key: string
readonly kind: "secret" | "env"
readonly value: string
}
| { readonly _tag: "AliasTargetMissing"; readonly key: string; readonly target: string }
| { readonly _tag: "AliasSelfReference"; readonly key: string }
| { readonly _tag: "AliasChained"; readonly key: string; readonly target: string }
| {
readonly _tag: "AliasCrossType"
readonly key: string
readonly kind: "secret" | "env"
readonly targetKind: "secret" | "env"
}
| {
readonly _tag: "AliasValueConflict"
readonly key: string
readonly kind: "secret" | "env"
readonly field: string
}

| Tag | When | | -------------------- | ----------------------------------------------------------------------------------- | | AliasInvalidSyntax | from_key is not formatted as "secret.<KEY>" or "env.<KEY>" | | AliasTargetMissing | from_key references a target that doesn’t exist in the resolved config | | AliasSelfReference | An entry’s from_key points at itself | | AliasChained | The target is itself an alias (only single-hop aliasing is supported) | | AliasCrossType | A secret entry aliases an env entry or vice versa (same-type aliasing only) | | AliasValueConflict | The entry declares both from_key and a value field (encrypted_value or value) |

Union of all error types that can occur during boot:

type BootError =
| ConfigError
| FnoxError
| CatalogError
| AliasError
| { readonly _tag: "AuditFailed"; readonly audit: AuditResult; readonly message: string }
| IdentityError

The AuditFailed variant includes the full AuditResult for inspection.

Use _tag for exhaustive pattern matching:

import type { ConfigError } from "envpkt"
function handleError(err: ConfigError): string {
switch (err._tag) {
case "FileNotFound":
return `Config not found: ${err.path}`
case "ParseError":
return `TOML syntax error: ${err.message}`
case "ValidationError":
return `Validation failed: ${err.errors.toArray().join(", ")}`
case "ReadError":
return `Read error: ${err.message}`
}
}

Or use functype’s Either.fold:

loadConfig("envpkt.toml").fold(
(err) => console.error(`[${err._tag}]`, err),
(config) => console.log("Loaded:", config),
)