{"record":{"id":"68c8e2934a399a56","repo":"can1357/oh-my-pi","slug":"invalid-bash-env-name-key","errorCode":null,"errorMessage":"Invalid bash env name: ${key}","messagePattern":"Invalid bash env name: (.+?)","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/bash.ts","lineNumber":391,"sourceCode":"\t  };\n\ninterface ManagedBashJobHandle {\n\tjobId: string;\n\tcompletion: Promise<ManagedBashJobCompletion>;\n\tgetLatestText: () => string;\n\tstopUpdates: () => void;\n}\n\nfunction normalizeResultOutput(result: BashResult | BashInteractiveResult): string {\n\treturn result.output || \"\";\n}\n\nfunction normalizeBashEnv(env: Record<string, string> | undefined): Record<string, string> | undefined {\n\tif (!env || Object.keys(env).length === 0) return undefined;\n\tconst normalized: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(env)) {\n\t\tif (!BASH_ENV_NAME_PATTERN.test(key)) {\n\t\t\tthrow new ToolError(`Invalid bash env name: ${key}`);\n\t\t}\n\t\tnormalized[key] = value;\n\t}\n\treturn normalized;\n}\n\nfunction escapeBashEnvValueForDisplay(value: unknown): string {\n\treturn String(value)\n\t\t.replaceAll(\"\\\\\", \"\\\\\\\\\")\n\t\t.replaceAll(\"\\n\", \"\\\\n\")\n\t\t.replaceAll(\"\\r\", \"\\\\r\")\n\t\t.replaceAll(\"\\t\", \"\\\\t\")\n\t\t.replaceAll('\"', '\\\\\"')\n\t\t.replaceAll(\"$\", \"\\\\$\")\n\t\t.replaceAll(\"`\", \"\\\\`\");\n}\n\nfunction formatBashEnvAssignments(env: Record<string, unknown> | undefined): string {","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/bash.ts#L373-L409","documentation":"normalizeBashEnv validates each key of the tool call's env parameter against BASH_ENV_NAME_PATTERN before applying it to the bash process. Any key containing characters outside the allowed identifier set (POSIX-style env names like MY_VAR) throws this ToolError naming the offending key, so an invalid variable never reaches the shell.","triggerScenarios":"A tool call supplies env with an invalid name — e.g. 'MY-VAR' (hyphen), '1PATH' (leading digit), 'FOO BAR' (space), 'export FOO' (accidentally passing a shell statement), or an empty key — so BASH_ENV_NAME_PATTERN.test(key) fails.","commonSituations":"LLM-generated tool arguments including shell syntax in env keys; copying 'KEY=value' pairs (with '=value') into env keys; intended lowercase-with-dashes names that are invalid for POSIX env vars.","solutions":["Rename the key to a valid shell identifier: letters, digits, underscores only, not starting with a digit (e.g. MY_VAR).","Remove any '=value' from the key — values belong in the value field, not the key.","Strip shell syntax; pass plain names like FOO, not 'export FOO' or 'FOO=1'.","Set unconventional variables inside the command itself if the name cannot be made pattern-valid."],"exampleFix":"// before\nawait bash.run(cmd, { env: { \"MY-VAR\": \"1\" } });\n// after\nawait bash.run(cmd, { env: { MY_VAR: \"1\" } });","handlingStrategy":"validation","validationCode":"const BASH_ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;\nfor (const k of Object.keys(env ?? {})) if (!BASH_ENV_NAME.test(k)) throw new Error(`Invalid bash env name: ${k}`);","typeGuard":"const isValidEnvName = (k: string): boolean => /^[A-Za-z_][A-Za-z0-9_]*$/.test(k);","tryCatchPattern":"try { await bash.run(cmd, { env }); } catch (e) { if (e instanceof ToolError && e.message.startsWith('Invalid bash env name:')) { /* sanitize the named key and retry */ } else throw e; }","preventionTips":["Validate env keys against /^[A-Za-z_][A-Za-z0-9_]*$/ before sending tool calls.","Never put '=value' or shell keywords (export) in env keys.","Use underscores instead of hyphens in variable names.","Constrain LLM-generated env args with a JSON schema pattern."],"tags":["bash","env","validation"],"backgroundTag":"invalid-env-variable-name","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}