Skip to content
Effect 4.0 is here. One ecosystem. Zero dependencies.

CryptoError unstable

The CryptoError returned by the effect/crypto modules, and the reasons it carries.

Every failure is one CryptoError whose module and method name the operation, such as "Aead" and "decrypt", and whose reason says what went wrong: InvalidArgument, InvalidKey, DecryptionFailed, Unsupported, or NotExtractable.

Gotchas

The error is not serializable, so it cannot be a typed failure in an Rpc or HttpApi schema. Map it before it reaches a client, for example DecryptionFailed to a 401. Sending crypto failure detail to clients is how oracles leak.

9 exports Since v4.0.0 Source

Errors

CryptoError

unstable
Since v4.0.0

Error returned by the effect/crypto modules.

When to use

Use to handle failures from any effect/crypto operation, matching on reason to separate caller mistakes from failed decryption.

Details

module and method name the operation, such as "Aead" and "decrypt". The message reads "Aead.decrypt: <reason message>". The error's cause is the reason's cause, when it has one.

See

Signature

declare class CryptoError extends YieldableError<this> & {
readonly _tag: "CryptoError";
} & Readonly<{
readonly method: string;
readonly module: string;
readonly reason: CryptoErrorReason;
}> {
constructor(args: {
readonly method: string;
readonly module: string;
readonly reason: CryptoErrorReason;
});
readonly "~effect/crypto/CryptoError": "~effect/crypto/CryptoError";
readonly cause: unknown;
message: string;
}

Example Recovering from failed decryption

import { Effect } from "effect"
import { CryptoError } from "effect/crypto"
const decrypt = Effect.fail(
new CryptoError.CryptoError({
module: "Aead",
method: "decrypt",
reason: new CryptoError.DecryptionFailed()
})
)
const program = decrypt.pipe(
Effect.catchReason("CryptoError", "DecryptionFailed", () => Effect.succeed("rejected"))
)
await Effect.runPromise(program) // => "rejected"

CryptoErrorReason

type unstable
Since v4.0.0

Union of the reasons carried by CryptoError.

Signature

type CryptoErrorReason = InvalidArgument | InvalidKey | DecryptionFailed | Unsupported | NotExtractable
Since v4.0.0

Reason for a decryption or unwrap that failed its integrity check, or a CBC ciphertext with bad padding or length.

Details

The reason is identical for every cause and carries no cause or runtime message, so callers cannot tell a tampered tag from bad padding. Keeping either would create a padding oracle.

Signature

declare class DecryptionFailed extends YieldableError<this> & {
readonly _tag: "DecryptionFailed";
} & Readonly<{}> {
constructor(args: void);
readonly "~effect/crypto/CryptoError/Reason": "~effect/crypto/CryptoError/Reason";
message: string;
}
Since v4.0.0

Reason for an argument that the operation rejects before using the key or data, such as a wrong nonce length, an out-of-range iteration count, or info passed to a key derivation other than HKDF.

Signature

declare class InvalidArgument extends YieldableError<this> & {
readonly _tag: "InvalidArgument";
} & Readonly<{
readonly cause?: unknown;
readonly description: string;
}> {
constructor(args: {
readonly cause?: unknown;
readonly description: string;
});
readonly "~effect/crypto/CryptoError/Reason": "~effect/crypto/CryptoError/Reason";
message: string;
}

InvalidKey

unstable
Since v4.0.0

Reason for key material that is rejected, such as a wrong raw key length, malformed DER, PEM, or JWK data, a CryptoKey that does not match the typed key, or a peer public key that produces an all-zero shared secret.

Signature

declare class InvalidKey extends YieldableError<this> & {
readonly _tag: "InvalidKey";
} & Readonly<{
readonly cause?: unknown;
readonly description: string;
}> {
constructor(args: {
readonly cause?: unknown;
readonly description: string;
});
readonly "~effect/crypto/CryptoError/Reason": "~effect/crypto/CryptoError/Reason";
message: string;
}
Since v4.0.0

Reason for exporting or wrapping a CryptoKey that was created as non-extractable.

Signature

declare class NotExtractable extends YieldableError<this> & {
readonly _tag: "NotExtractable";
} & Readonly<{
readonly cause?: unknown;
readonly description: string;
}> {
constructor(args: {
readonly cause?: unknown;
readonly description: string;
});
readonly "~effect/crypto/CryptoError/Reason": "~effect/crypto/CryptoError/Reason";
message: string;
}

Unsupported

unstable
Since v4.0.0

Reason for an algorithm or key that a layer does not provide, such as Argon2id under Kdf.layerWebCrypto, or a CryptoKey-backed key passed to a layer that cannot use it.

Signature

declare class Unsupported extends YieldableError<this> & {
readonly _tag: "Unsupported";
} & Readonly<{
readonly cause?: unknown;
readonly description: string;
}> {
constructor(args: {
readonly cause?: unknown;
readonly description: string;
});
readonly "~effect/crypto/CryptoError/Reason": "~effect/crypto/CryptoError/Reason";
message: string;
}

Guards

Since v4.0.0

Checks whether a value is a CryptoError.

Signature

declare function isCryptoError(u: unknown): u is CryptoError
Since v4.0.0

Checks whether a value is one of the reasons carried by CryptoError.

Signature

declare function isCryptoErrorReason(u: unknown): u is CryptoErrorReason