Skip to main content

Failure catalog

Every condition under which a Pebble builtin, prelude method, or stdlib function aborts the script. Aborting means the entire transaction is rejected — there is no partial state on-chain. Use this catalog when generating defensive code: validate inputs before calling, or arrange the call so failure is unreachable.

The columns:

  • Symbol — fully qualified name (e.g. List<T>.head()).
  • Fails when — preconditions that, if violated, abort.
  • Safer alternative — when one exists.

Aborting builtins

Integer division / modulo

SymbolFails whenSafer alternative
a / b (operator)b == 0Guard with b != 0 before dividing.
a % b (operator)b == 0Same.
std.int.divide(a, b)b == 0Same.
std.int.mod(a, b)b == 0Same.
std.int.quotient(a, b)b == 0Same.
std.int.remainder(a, b)b == 0Same.
std.builtins.divideInteger(a,b)b == 0Same.
std.builtins.quotientIntegerb == 0Same.
std.builtins.remainderIntegerb == 0Same.
std.builtins.modIntegerb == 0Same.
std.builtins.expModInteger(b,e,m)m == 0Guard m != 0.
std.int.exponentiate(b, e)e < 0Check exponent sign before calling.

Byte-string indexing

SymbolFails whenSafer alternative
bytes.indexAt(i)i < 0 or i >= length()Check i < b.length() first.
std.bytes.indexAt(b, i)Same.Same.
std.builtins.indexByteString(b, i)Same.Same.
std.builtins.consByteString(n, b)n < 0 or n > 255Ensure byte value in 0–255.
std.builtins.decodeUtf8(b)b is not valid UTF-8Use raw bytes if validity can't be assured.

List operations

SymbolFails whenSafer alternative
List<T>.head()List is emptyGuard with xs.isEmpty() or use find.
List<T>.tail()List is emptySame.
std.list.head(xs)Same.Same.
std.list.tail(xs)Same.Same.
std.builtins.headList(xs)Same.Same.
std.builtins.tailList(xs)Same.Same.
xs[i] (list indexing)i < 0 or i >= length()Check i >= 0 && i < xs.length() before indexing. The list-vs-array conversion is not a safety win — both forms fail on out-of-range; see Cost and Complexity.

Array operations

SymbolFails whenSafer alternative
Array<T>.at(i)i < 0 or i >= length()Check bounds before calling.
std.array.at(xs, i)Same.Same.
xs[i] (array indexing)Same.Same.

LinearMap operations

SymbolFails whenSafer alternative
LinearMap<K,V>.head()Map is emptyGuard isEmpty().
LinearMap<K,V>.tail()Map is emptySame.
LinearMap<K,V>.lookup(k)Does not fail. Returns None{} when absent.

Optional destructuring

SymbolFails whenSafer alternative
const Some{ value } = opt;opt is None{} at runtimePattern-match with match opt { ... }.

data destructors

SymbolFails whenSafer alternative
std.builtins.unConstrData(d)d is not a ConstrUse chooseData to dispatch by tag first.
std.builtins.unMapData(d)d is not a MapSame.
std.builtins.unListData(d)d is not a ListSame.
std.builtins.unIData(d)d is not an ISame.
std.builtins.unBData(d)d is not a BSame.
std.data.strFromData(d)d is not B or its bytes aren't valid UTF-8Round-trip through bData(encodeUtf8(s)).

BLS12-381

SymbolFails whenSafer alternative
std.crypto.bls12_381.g1Uncompress(b)b isn't a valid 48-byte compressed G1 pointOnly feed it points produced by g1Compress or validated upstream.
std.crypto.bls12_381.g2Uncompress(b)b isn't a valid 96-byte compressed G2 pointSame.

Assertion forms

SymbolFails when
assert <expr><expr> evaluates to false.
fail "<message>"Always — this is the explicit-failure form. The <message> is recorded in trace.
Destructuring const binding with wrong variantE.g. const Some{ value } = none_value;. The runtime constructor check fails.

Non-aborting "soft failure" surfaces

Worth knowing because they look like failures but aren't:

SymbolBehaviour
std.crypto.verifyEd25519Signature(pk, m, s)Returns false on any malformed input — the script does not abort.
std.crypto.verifyEcdsaSecp256k1SignatureSame.
std.crypto.verifySchnorrSecp256k1SignatureSame.
Value.amountOf(policy, name)Returns 0 if (policy, name) is absent.
std.builtins.lookupCoinReturns 0 if absent.
std.list.find(p, xs)Returns None{} when nothing matches.
std.linearMap.lookup(k, m)Returns None{} when k is absent.

Patterns

Guard before destructure. Prefer

match opt {
Some{ value: x }: useIt(x),
None{}: fallback()
}

over

const Some{ value: x } = opt; // aborts if None

Dispatch on data tag. When the shape isn't statically known:

const tag = std.builtins.chooseData(d, "Constr", "Map", "List", "I", "B");

then call the matching destructor.

assert after extraction. Pull values out, validate, then proceed. Each assert adds one branch to the budget — group conditions with && when they share evaluation cost.