clockworklabs/SpacetimeDB · error · TypeError

Environment ' ' enum cases must have names

Error message

Environment '${name}' enum cases must have names

What it means

Every enum variant used as an environment variable must have a string name, because that name becomes the literal value written into the environment. A variant whose name is missing or not a string cannot be encoded and triggers this TypeError.

Solutions

  1. Use the enum builder API so every variant gets a name
  2. Ensure each variant object passed to the sum type has a string name field
  3. Inspect the constructed AlgebraicType and add missing variant names

Example fix

// before
variants: [{ algebraicType: productType() }]
// after
variants: [{ name: 'Enabled', algebraicType: productType() }]
Defensive patterns

Strategy: validation

Validate before calling

function assertVariantNamesNamed(ty) {
  for (const v of ty.algebraicType.value.variants) {
    if (typeof v.name !== 'string') throw new TypeError('Every enum variant must have a string name');
  }
}

Type guard

const hasNamedVariants = (ty): ty is { algebraicType: { tag: 'Sum'; value: { variants: { name: string }[] } } } =>
  ty?.algebraicType?.tag === 'Sum' && ty.algebraicType.value.variants.every(v => typeof v.name === 'string');

Prevention

When it happens

Trigger: Building an enum type whose variant.name is undefined or non-string (e.g. a programmatically constructed AlgebraicType variant lacking a name) and using it as an env var.

Common situations: Hand-rolling AlgebraicTypeSum variants instead of using the enum builder; refactoring codegen that dropped variant names.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

      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]! }
          : { tag: 'Union', value: values };
    }
    return { name, ty, optional };
  });
}

View on GitHub (pinned to eddf9f5014)