{"record":{"id":"642d09ee859e4a60","repo":"microsoft/aspire","slug":"cannot-use-null-or-undefined-in-reference-expression","errorCode":null,"errorMessage":"Cannot use null or undefined in reference expression","messagePattern":"Cannot use null or undefined in reference expression","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/base.mts","lineNumber":261,"sourceCode":"    if (typeof matchValueOrWhenTrue === 'string') {\n        return new ReferenceExpression(condition, matchValueOrWhenTrue, whenTrueOrWhenFalse, whenFalse!);\n    }\n\n    return new ReferenceExpression(condition, 'True', matchValueOrWhenTrue, whenTrueOrWhenFalse);\n}\n\nregisterHandleWrapper('Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpression', (handle, client) =>\n    new ReferenceExpression(handle, client)\n);\n\n/**\n * Extracts a value for use in reference expressions.\n * Supports handles (objects) and string literals.\n * @internal\n */\nfunction extractHandleForExpr(value: unknown): unknown {\n    if (value === null || value === undefined) {\n        throw new Error('Cannot use null or undefined in reference expression');\n    }\n\n    // String literals - include directly in the expression\n    if (typeof value === 'string') {\n        return value;\n    }\n\n    // Number literals - convert to string\n    if (typeof value === 'number') {\n        return String(value);\n    }\n\n    // Handle objects - get their JSON representation\n    if (isHandleLike(value)) {\n        return value.toJSON();\n    }\n\n    // Objects with marshalled expression/handle payloads","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/base.mts#L243-L279","documentation":"The generated TypeScript runtime's internal extractHandleForExpr builds reference expressions from handles (server objects) and string literals only. Passing null or undefined is ambiguous — the runtime cannot represent either in a reference expression — so it throws this Error up front instead of producing a malformed expression that would fail on the server side.","triggerScenarios":"Calling a reference-expression building API (e.g. the `value`/expression helpers that call extractHandleForExpr) with null or undefined as the value — commonly from an unset variable, an optional field, or a failed lookup like env.get(...)/map lookup returning undefined.","commonSituations":"Optional endpoint or parameter lookups that return undefined at runtime; TypeScript optional chaining (`resource?.endpoint`) silently yielding undefined; object destructuring where the property does not exist; passing a variable before it is assigned.","solutions":["Check the value for null/undefined before passing it into the reference-expression helper, and substitute a string literal or a valid handle.","Trace where the undefined came from — a failed lookup or optional property — and fix the source (provide a default, fix the key, or await an async lookup).","If the value is legitimately optional, branch your code: build the expression only when the value exists, otherwise use a fallback string or skip the reference.","Add TypeScript strict null checks (strictNullChecks) so the compiler flags possibly-undefined values before they reach the helper."],"exampleFix":"// before\nconst endpoint = process.env.MAYBE_ENDPOINT;\nconst expr = value(endpoint);   // throws when undefined\n\n// after\nconst endpoint = process.env.MAYBE_ENDPOINT ?? 'http://localhost:8080';\nconst expr = value(endpoint);","handlingStrategy":"validation","validationCode":"function assertExprInput(v) {\n  if (v === null || v === undefined) throw new TypeError('Reference expression value must be a handle or string, got ' + v);\n  return v;\n}\n// call assertExprInput(x) before value(x)","typeGuard":"function isExprValue(v) { return typeof v === 'string' || (v !== null && v !== undefined && typeof v === 'object'); }","tryCatchPattern":"try {\n  const expr = value(input);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('null or undefined')) {\n    // fall back to a default literal or skip building the expression\n  }\n}","preventionTips":["Enable strictNullChecks so possibly-undefined values are caught at compile time.","Provide defaults for optional lookups (`?? fallback`) before building expressions.","Avoid optional chaining that can silently pass undefined into expression helpers."],"tags":["typescript","null","reference-expression","validation"],"backgroundTag":"null-argument","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"}