{"record":{"id":"cb33b43ed0b62575","repo":"clockworklabs/SpacetimeDB","slug":"invalid-environment-declaration-name","errorCode":null,"errorMessage":"Invalid environment declaration name","messagePattern":"Invalid environment declaration name","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/bindings-typescript/src/server/environment.ts","lineNumber":49,"sourceCode":"  Environment,\n  EnvironmentFor,\n  EnvironmentSchema,\n} from '../lib/environment';\n\n/** Produce metadata only. No environment value is embedded in the artifact. */\nexport function environmentDeclarations(\n  schema: EnvironmentSchema\n): EnvironmentDeclaration[] {\n  const entries = Object.entries(schema);\n  if (entries.length > MAX_ENV_VARS)\n    throw new TypeError('Too many environment declarations');\n  const bytes = new TextEncoder();\n  return entries.map(([name, definition]) => {\n    if (\n      !/^[A-Za-z_][A-Za-z0-9_]*$/.test(name) ||\n      bytes.encode(name).length > MAX_ENV_KEY_BYTES\n    ) {\n      throw new TypeError('Invalid environment declaration name');\n    }\n    const optional = definition instanceof OptionBuilder;\n    const inner = optional ? definition.value : definition;\n    let ty: EnvVarType;\n    if (inner instanceof StringBuilder) {\n      ty = { tag: 'String' };\n    } else {\n      const type: AlgebraicType = inner?.algebraicType;\n      if (type?.tag !== 'Sum' || !('variants' in inner)) {\n        throw new TypeError(\n          `Environment '${name}' must be a string or simple enum`\n        );\n      }\n      const values = type.value.variants.map(variant => {\n        if (\n          variant.algebraicType.tag !== 'Product' ||\n          variant.algebraicType.value.elements.length !== 0\n        ) {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/eddf9f5014579a50d4b67630e28b6e15cad9c4af/crates/bindings-typescript/src/server/environment.ts#L31-L67","documentation":"Each environment variable name must be a valid identifier (matching /^[A-Za-z_][A-Za-z0-9_]*$/) and fit within MAX_ENV_KEY_BYTES when UTF-8 encoded. This ensures the name can be emitted as an identifier/attribute in generated artifacts and referenced uniformly across client languages.","triggerScenarios":"Declaring an env var whose name starts with a digit, contains hyphens/dots/spaces, is an empty string, or whose UTF-8 length exceeds MAX_ENV_KEY_BYTES, then running module build via environmentDeclarations().","commonSituations":"Copy-pasting OS env names like 'MY-APP-KEY' or 'my.app.key' into the schema; using lowercase dotted names from config files; very long generated key names.","solutions":["Rename the variable to match /^[A-Za-z_][A-Za-z0-9_]*$/ (letters, digits, underscore; not starting with a digit)","Shorten the name so its UTF-8 encoding is within MAX_ENV_KEY_BYTES","Validate names with a regex/length check before building the schema"],"exampleFix":"// before\nconst schema = { 'my-app-key': str };\n// after\nconst schema = { my_app_key: str };","handlingStrategy":"validation","validationCode":"const ENV_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\nfunction assertValidEnvNames(schema) {\n  for (const name of Object.keys(schema)) {\n    if (!ENV_NAME_RE.test(name) || new TextEncoder().encode(name).length > MAX_ENV_KEY_BYTES) {\n      throw new TypeError(`Invalid env name: ${name}`);\n    }\n  }\n}","typeGuard":"const isValidEnvName = (n: string): boolean => /^[A-Za-z_][A-Za-z0-9_]*$/.test(n) && new TextEncoder().encode(n).length <= MAX_ENV_KEY_BYTES;","tryCatchPattern":"try {\n  environmentDeclarations(schema);\n} catch (e) {\n  if (e instanceof TypeError && e.message === 'Invalid environment declaration name') {\n    console.error('Fix env key naming (identifier chars, <= MAX_ENV_KEY_BYTES bytes)');\n  } else throw e;\n}","preventionTips":["Use only SCREAMING_SNAKE_CASE identifiers for env keys","Lint schema keys with the identifier regex in CI","Avoid copy-pasting OS env names with hyphens or dots"],"tags":["environment","naming","validation","typescript"],"backgroundTag":"invalid-identifier-format","analyzedSha":"eddf9f5014579a50d4b67630e28b6e15cad9c4af","analyzedAt":"2026-09-20T12:15:59.611Z","contentChangedAt":"2026-09-20T12:15:59.611Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}