{"record":{"id":"2f2a1b6c5bace820","repo":"dagger/dagger","slug":"invalid-key-q-unterminated-quoted-path-segment","errorCode":null,"errorMessage":"invalid key %q: unterminated quoted path segment","messagePattern":"invalid key %q: unterminated quoted path segment","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/workspace/config.go","lineNumber":1098,"sourceCode":"\t\ti++\n\t\tswitch ch {\n\t\tcase '\\\\':\n\t\t\tr, next, err := parseConfigPathEscape(key, i)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", 0, err\n\t\t\t}\n\t\t\tb.WriteRune(r)\n\t\t\ti = next\n\t\tcase '\"':\n\t\t\treturn b.String(), i, nil\n\t\tdefault:\n\t\t\tif ch < 0x20 || ch == 0x7f {\n\t\t\t\treturn \"\", 0, fmt.Errorf(\"invalid key %q: unescaped control character in quoted path segment\", key)\n\t\t\t}\n\t\t\tb.WriteByte(ch)\n\t\t}\n\t}\n\treturn \"\", 0, fmt.Errorf(\"invalid key %q: unterminated quoted path segment\", key)\n}\n\nfunc parseConfigPathEscape(key string, start int) (rune, int, error) {\n\tif start >= len(key) {\n\t\treturn 0, 0, fmt.Errorf(\"invalid key %q: trailing escape in quoted path segment\", key)\n\t}\n\n\tescaped := key[start]\n\tnext := start + 1\n\tswitch escaped {\n\tcase 'b':\n\t\treturn '\\b', next, nil\n\tcase 't':\n\t\treturn '\\t', next, nil\n\tcase 'n':\n\t\treturn '\\n', next, nil\n\tcase 'f':\n\t\treturn '\\f', next, nil","sourceCodeStart":1080,"sourceCodeEnd":1116,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/core/workspace/config.go#L1080-L1116","documentation":"parseBasicConfigPathSegment throws this when a double-quoted path segment in a config key is never closed with a matching double-quote before the end of the key string. The parser reached the end of input while still inside the quoted segment.","triggerScenarios":"Passing a key like \"ignore.foo (missing closing quote) or a key where an unescaped \\\\ swallowed the closing quote, e.g. \"ignore\\\" leaving the segment open.","commonSituations":"Hand-written keys with a dropped closing quote; template-generated keys where a variable containing a quote shifted quoting; shell quoting stripped one of the quotes before it reached the API.","solutions":["Add the missing closing double-quote at the end of the segment","If the segment should contain a literal quote, escape it as \\\"","For segments needing no escape processing, use single-quote literal syntax: 'segment'"],"exampleFix":"// before\nsetConfig(\"\"ignore.nested, value) // missing closing quote\n// after\nsetConfig(\"ignore.nested\", value)","handlingStrategy":"validation","validationCode":"func quotesBalanced(key string) bool {\n\tinBasic, inLiteral := false, false\n\tfor i := 0; i < len(key); i++ {\n\t\tswitch {\n\t\tcase inBasic && key[i] == '\\\\':\n\t\t\ti++\n\t\tcase inBasic && key[i] == '\"':\n\t\t\tinBasic = false\n\t\tcase !inLiteral && key[i] == '\"':\n\t\t\tinBasic = true\n\t\tcase !inBasic && key[i] == '\\'':\n\t\t\tinLiteral = !inLiteral\n\t\t}\n\t}\n\treturn !inBasic && !inLiteral\n}","typeGuard":null,"tryCatchPattern":"if err := writeConfig(key, val); err != nil {\n\tif strings.Contains(err.Error(), \"unterminated quoted path segment\") {\n\t\treturn fmt.Errorf(\"key %q is missing a closing quote\", key)\n\t}\n\treturn err\n}","preventionTips":["Count quotes when generating keys programmatically","Prefer single-quote literal segments to avoid escape pitfalls","Test key construction helpers with quoting edge cases"],"tags":["config","parsing","quoting"],"backgroundTag":"invalid-config-key-syntax","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}