{"record":{"id":"eb9379bb59fd90fc","repo":"different-ai/openwork","slug":"keyerror-i18n-validation-message-returned-by-vali","errorCode":null,"errorMessage":"keyError (i18n validation message returned by validateKey)","messagePattern":"keyError \\(i18n validation message returned by validateKey\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/app/src/react-app/domains/settings/pages/environment-variable-provider.tsx","lineNumber":146,"sourceCode":"  const markChangesPending = useCallback(() => {\n    clearOpenworkEnvSystemContextCache();\n    queryClient.setQueryData([\"settings\", \"environment\", \"pending-changes\", runtimeKey], true);\n    resetApply();\n    client?.setUserEnvPendingChanges(true, runtimeKey).catch(() => undefined);\n\n    toast.info(t(\"settings.environment.restart_required\"));\n  }, [client, resetApply, queryClient, runtimeKey]);\n\n  const { mutate: modifyAsync, isPending: isModifying, reset: resetModify, error: modifyError } = useMutation({\n    mutationFn: async (nextEditor: EnvironmentEditorDraft) => {\n      if (!client) {\n        throw new Error(t(\"app.unknown_error\"));\n      }\n\n      const keyError = validateKey(nextEditor.key);\n\n      if (keyError) {\n        throw new Error(keyError);\n      }\n\n      const key = nextEditor.key.trim();\n      const existingItems = queryClient.getQueryData<{ items: EnvironmentVariableItem[] }>(\n        environmentUserEnvQueryKey(runtimeKey),\n      )?.items;\n\n      if (nextEditor.mode === \"add\" && existingItems?.some((item) => item.key === key)) {\n        throw new Error(t(\"settings.environment.validation_duplicate\"));\n      }\n\n      return client.upsertUserEnv([{ key, value: nextEditor.value }]);\n    },\n    onSuccess: async () => {\n      markChangesPending();\n\n      await queryClient.invalidateQueries({\n        queryKey: environmentUserEnvQueryKey(runtimeKey),","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/app/src/react-app/domains/settings/pages/environment-variable-provider.tsx#L128-L164","documentation":"The modify mutation validates the environment variable key with validateKey before persisting. If the key is invalid (empty, contains illegal characters, etc.), the returned i18n message is thrown as the mutation error so the UI surfaces it next to the form.","triggerScenarios":"Calling modifyAsync with a draft whose key fails validateKey — e.g. empty key, whitespace-only key, or a key containing characters not allowed in environment variable names (spaces, '=', special symbols).","commonSituations":"Typing an invalid env var name like \"MY VAR\" or \"PATH=extra\"; clearing the key field then saving; pasting a line from a .env file including \"KEY=value\" into the key input.","solutions":["Correct the key to a valid identifier (typically [A-Za-z_][A-Za-z0-9_]*)","Inspect validateKey's rules in the codebase and match them","Trim whitespace from the key before submitting"],"exampleFix":"// before\nkey: \"MY VAR\"\n// after\nkey: \"MY_VAR\"","handlingStrategy":"validation","validationCode":"const keyError = validateKey(key);\nif (keyError) {\n  setFieldError(\"key\", keyError);\n  return;\n}\nmodifyAsync({ key, value, mode });","typeGuard":"const isValidEnvKey = (k: string) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(k.trim());","tryCatchPattern":"try {\n  modifyAsync(draft);\n} catch (e) {\n  setFieldError(\"key\", e.message);\n}","preventionTips":["Validate the key inline as the user types","Enforce identifier-style key patterns in the input","Trim keys before submission"],"tags":["validation","environment-variables","i18n"],"backgroundTag":"schema-validation-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}