{"record":{"id":"e027287a650f86a0","repo":"microsoft/aspire","slug":"aspire-terminal-host-invocation-args-has-unterminated","errorCode":null,"errorMessage":"ASPIRE_TERMINAL_HOST_INVOCATION_ARGS has unterminated {(inDouble ? \"double\" : \"single\")} quote.","messagePattern":"ASPIRE_TERMINAL_HOST_INVOCATION_ARGS has unterminated (.+?) quote\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/Lifecycle/TerminalHostEventingSubscriber.cs","lineNumber":209,"sourceCode":"                case ' ':\n                case '\\t':\n                    if (hasContent)\n                    {\n                        result.Add(current.ToString());\n                        current.Clear();\n                        hasContent = false;\n                    }\n                    break;\n                default:\n                    current.Append(c);\n                    hasContent = true;\n                    break;\n            }\n        }\n\n        if (inDouble || inSingle)\n        {\n            throw new InvalidOperationException(\n                $\"ASPIRE_TERMINAL_HOST_INVOCATION_ARGS has unterminated {(inDouble ? \"double\" : \"single\")} quote.\");\n        }\n\n        if (hasContent)\n        {\n            result.Add(current.ToString());\n        }\n\n        return [.. result];\n    }\n}\n","sourceCodeStart":191,"sourceCodeEnd":221,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Lifecycle/TerminalHostEventingSubscriber.cs#L191-L221","documentation":"ParseInvocationArgs tokenizes the ASPIRE_TERMINAL_HOST_INVOCATION_ARGS environment variable using shell-like quote rules (double and single quotes, backslash escapes). If the value ends while a quote is still open, the parser cannot determine argument boundaries and throws InvalidOperationException naming which quote type was unterminated.","triggerScenarios":"Setting ASPIRE_TERMINAL_HOST_INVOCATION_ARGS with an odd number of unescaped double (\") or single (') quotes, e.g. \"--verbose 'value\" — the value ends while the parser is still inside a quoted section.","commonSituations":"Hand-editing the env var in launchSettings.json or shell export and dropping a closing quote; interpolating values that themselves contain quotes; copying a shell command with quotes into the variable without escaping; platform quoting differences (Windows vs bash).","solutions":["Fix ASPIRE_TERMINAL_HOST_INVOCATION_ARGS so every quote is paired, or remove quotes entirely if arguments contain no spaces.","Escape embedded quotes with backslash (\\\" and \\\\) instead of nesting quotes.","Print/log the variable value and count quotes to find the unbalanced one.","Avoid quotes by splitting arguments so each one is a separate simple token."],"exampleFix":"// before (unterminated single quote)\nASPIRE_TERMINAL_HOST_INVOCATION_ARGS=--project 'MyApp\n\n// after\nASPIRE_TERMINAL_HOST_INVOCATION_ARGS=--project MyApp","handlingStrategy":"validation","validationCode":"var args = Environment.GetEnvironmentVariable(\"ASPIRE_TERMINAL_HOST_INVOCATION_ARGS\");\nif (args is not null && (args.Count(c => c == '\"') % 2 != 0 || args.Count(c => c == '\\'') % 2 != 0))\n{\n    throw new FormatException(\"ASPIRE_TERMINAL_HOST_INVOCATION_ARGS has an unbalanced quote.\");\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    ParseInvocationArgs(raw);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"unterminated\"))\n{\n    logger.LogError(ex, \"Fix quoting in ASPIRE_TERMINAL_HOST_INVOCATION_ARGS: {Value}\", raw);\n}","preventionTips":["Keep argument values free of spaces so quotes are unnecessary.","Escape embedded quotes with backslash rather than nesting quote types.","Validate launchSettings.json/shell exports containing this variable after every edit.","Prefer an args array or config file over a single quoted string when possible."],"tags":["env-var","quoting","parsing","aspire-cli"],"backgroundTag":"invalid-env-var-value","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}