{"record":{"id":"42dc2e23554ef579","repo":"jdx/mise","slug":"user-service-environment-key-key-cannot","errorCode":null,"errorMessage":"user service '{}': environment key {key:?} cannot be set through cmd.exe","messagePattern":"user service '(.+?)': environment key (.+?) cannot be set through cmd\\.exe","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/scheduled_tasks.rs","lineNumber":211,"sourceCode":"    }\n    out.push_str(\"    </Exec>\\n  </Actions>\\n\");\n    out.push_str(\"</Task>\\n\");\n    Ok(out)\n}\n\n/// Split the command line into the executable and its arguments. Task\n/// Scheduler has no environment block, so variables are set through\n/// `cmd.exe`, which reinterprets some characters; values that it would\n/// change are rejected rather than passed through differently.\nfn exec_action(request: &ScheduledTaskRequest) -> Result<(String, String)> {\n    let (program, args) = split_command(&request.command);\n    if request.environment.is_empty() {\n        return Ok((program, args));\n    }\n    let mut sets = vec![];\n    for (key, value) in &request.environment {\n        if key.is_empty() || key.contains(['=', '\"', '%', '\\n', '\\r']) {\n            bail!(\n                \"user service '{}': environment key {key:?} cannot be set through cmd.exe\",\n                request.name\n            );\n        }\n        if let Some(c) = value\n            .chars()\n            .find(|c| matches!(c, '\"' | '%' | '&' | '|' | '<' | '>' | '^' | '\\n' | '\\r'))\n        {\n            bail!(\n                \"user service '{}': environment value for {key} contains {c:?}, which cmd.exe would reinterpret; set it inside the program instead\",\n                request.name\n            );\n        }\n        sets.push(format!(\"set \\\"{key}={value}\\\"\"));\n    }\n    // the command line goes through cmd.exe too: what it would split or\n    // chain is rejected the same way, rather than run differently\n    if let Some(c) = format!(\"{program} {args}\")","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/scheduled_tasks.rs#L193-L229","documentation":"When a user service (scheduled task) declares an `environment` map, the values must be injected via a cmd.exe wrapper, and cmd.exe cannot safely set arbitrary environment keys. Keys that are empty or contain '=', quotes, '%', or newlines would break or be reinterpreted by cmd.exe, so exec_action (called by render_xml) rejects them.","triggerScenarios":"Calling the service/task rendering path (render_xml -> exec_action) on Windows for a service whose request.environment contains a key that is empty or contains '=', '\"', '%', '\\n', or '\\r'.","commonSituations":"Copying Linux-style env definitions with '=' inside keys or quoted keys; keys built by string interpolation that accidentally include a percent sign; multiline keys pasted from a .env file.","solutions":["Sanitize the environment key: remove '=', quotes, '%' and line breaks","Set the variable inside the program/script instead of via request.environment","Wrap the whole env setup in a script file and drop the environment map"],"exampleFix":"// before\nenvironment: { \"PATH=EXTRA\": \"/x\" }\n// after\nenvironment: { \"PATH_EXTRA\": \"/x\" }","handlingStrategy":"validation","validationCode":"const badKey = Object.keys(svc.environment).find(k => !k || /[=\"%'\\r\\n]/.test(k));\nif (badKey !== undefined) throw new Error(`env key ${JSON.stringify(badKey)} not cmd.exe-safe`);","typeGuard":"function isCmdSafeKey(k) { return typeof k === 'string' && k.length > 0 && !/[=\"%'\\r\\n]/.test(k); }","tryCatchPattern":"try { renderServiceXml(svc); } catch (e) { if (String(e).includes('cannot be set through cmd.exe')) { sanitizeEnvKeys(svc.environment); } else throw e; }","preventionTips":["Use only [A-Za-z_][A-Za-z0-9_]* for environment keys","Never build env keys by interpolating raw strings","Move exotic variables into the program's own config instead of task environment"],"tags":["windows","cmd-exe","scheduled-tasks","environment"],"backgroundTag":"invalid-argument-value","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}