clockworklabs/SpacetimeDB · error · TypeError

Environment ' ' cannot use an enum payload

Error message

Environment '${name}' cannot use an enum payload

What it means

Enums used as environment variables must be 'simple': every variant must be a unit variant (a Product type with zero elements). Variants carrying payloads cannot be serialized to a flat environment string, so environmentDeclarations() rejects them.

Solutions

  1. Define a dedicated unit-only enum for the environment variable
  2. Map payload variants to separate string variables (e.g. 'mode' plus 'mode_count')
  3. Change the variant to carry no payload

Example fix

// before
enum Cfg { Plain, WithCount(u32) }
// after
enum Cfg { Plain, WithCount } // plus a separate count env var
Defensive patterns

Strategy: validation

Validate before calling

function isSimpleEnum(ty) {
  return ty?.algebraicType?.tag === 'Sum' &&
    ty.algebraicType.value.variants.every(v =>
      v.algebraicType.tag === 'Product' && v.algebraicType.value.elements.length === 0);
}

Try / catch

try {
  environmentDeclarations(schema);
} catch (e) {
  if (e instanceof TypeError && /cannot use an enum payload/.test(e.message)) {
    console.error('Define a unit-only enum for this env var');
  } else throw e;
}

Prevention

When it happens

Trigger: Declaring an env var whose enum type has a variant with associated data, e.g. enum Cfg { Plain, WithCount(u32) }, then building the module.

Common situations: Reusing a rich application enum (with data-carrying variants) directly as an environment type instead of defining a dedicated unit-only enum.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-09-20). Data as JSON: /api/errors/6d6aa974572cc6a2. Report an issue: GitHub.

Appendix: source

Thrown at crates/bindings-typescript/src/server/environment.ts:68

    }
    const optional = definition instanceof OptionBuilder;
    const inner = optional ? definition.value : definition;
    let ty: EnvVarType;
    if (inner instanceof StringBuilder) {
      ty = { tag: 'String' };
    } else {
      const type: AlgebraicType = inner?.algebraicType;
      if (type?.tag !== 'Sum' || !('variants' in inner)) {
        throw new TypeError(
          `Environment '${name}' must be a string or simple enum`
        );
      }
      const values = type.value.variants.map(variant => {
        if (
          variant.algebraicType.tag !== 'Product' ||
          variant.algebraicType.value.elements.length !== 0
        ) {
          throw new TypeError(
            `Environment '${name}' cannot use an enum payload`
          );
        }
        if (typeof variant.name !== 'string')
          throw new TypeError(
            `Environment '${name}' enum cases must have names`
          );
        if (bytes.encode(variant.name).length > MAX_ENV_VALUE_BYTES)
          throw new TypeError(`Environment '${name}' literal is too long`);
        return variant.name;
      });
      if (values.length === 0 || new Set(values).size !== values.length)
        throw new TypeError(
          `Environment '${name}' needs a nonempty literal union`
        );
      ty =
        values.length === 1
          ? { tag: 'StringLiteral', value: values[0]! }

View on GitHub (pinned to eddf9f5014)