{"record":{"id":"9f81c78d440abd7b","repo":"jdx/mise","slug":"unterminated-raw-go-string","errorCode":null,"errorMessage":"unterminated raw Go string","messagePattern":"unterminated raw Go string","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/task/workspace/go.rs","lineNumber":191,"sourceCode":"    if !rest.starts_with(char::is_whitespace) {\n        return None;\n    }\n    Some(rest.trim())\n}\n\nfn parse_argument(value: &str) -> Result<String> {\n    if value.is_empty() {\n        bail!(\"directive requires one argument\");\n    }\n    if let Some(value) = value.strip_prefix('\"') {\n        let Some(value) = value.strip_suffix('\"') else {\n            bail!(\"unterminated interpreted Go string\");\n        };\n        return unescape_go_string(value);\n    }\n    if let Some(value) = value.strip_prefix('`') {\n        let Some(value) = value.strip_suffix('`') else {\n            bail!(\"unterminated raw Go string\");\n        };\n        if value.contains('`') {\n            bail!(\"unexpected raw Go string delimiter\");\n        }\n        return Ok(value.to_string());\n    }\n    if value.split_whitespace().count() != 1 {\n        bail!(\"directive requires exactly one argument\");\n    }\n    Ok(value.to_string())\n}\n\nfn unescape_go_string(value: &str) -> Result<String> {\n    let mut characters = value.chars();\n    let mut unescaped = String::new();\n    while let Some(character) = characters.next() {\n        if character == '\"' {\n            bail!(\"unexpected interpreted Go string delimiter\");","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/task/workspace/go.rs#L173-L209","documentation":"parse_argument treats arguments starting with a backtick as Go raw strings and requires a matching closing backtick; when strip_suffix('`') fails the token is an unterminated raw string and parsing aborts. Raw strings in go files span to the next backtick, so one unclosed delimiter consumes the rest of the line.","triggerScenarios":"go.work or go.mod contains `use `./api` style entries where the closing backtick is missing; a single stray backtick line inside a use (...) block; paths edited with mismatched keyboard layouts producing the opener only.","commonSituations":"Copying Windows paths with backticks used as accidental quote substitutes; hand-adding quoting for paths with spaces; merge artifacts leaving a lone backtick.","solutions":["Add the closing backtick so the token is `./api` wrapped in a backtick pair, or drop the backticks entirely for simple paths","Use interpreted quotes (\"...\") when the path contains no escapes; raw strings cannot contain any backtick at all","Validate the file with `go work sync` / `go build` after editing"],"exampleFix":"# before (go.work)\nuse `./api\n\n# after\nuse ./api","handlingStrategy":"validation","validationCode":"fn backticks_balanced(token: &str) -> bool {\n    if let Some(body) = token.strip_prefix('`') {\n        body.ends_with('`')\n    } else {\n        true\n    }\n}","typeGuard":"fn is_closed_raw_string(token: &str) -> bool {\n    token.strip_prefix('`').is_none_or(|body| body.ends_with('`'))\n}","tryCatchPattern":"Err(report) if report.to_string().contains(\"unterminated raw Go string\") => {\n    // raw strings buy nothing for plain paths; strip the stray backtick and retry\n    let token = token.trim_start_matches('`');\n    directories.push(PathBuf::from(token));\n}","preventionTips":["Avoid backticks entirely in go.work/go.mod paths; they are markdown formatting, not quoting","If quoting is needed, use interpreted \\\"...\\\" strings","Check pasted entries for stray ` characters"],"tags":["go","go-work","parse","string-literal","syntax"],"backgroundTag":"unterminated-string-literal","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}