{"record":{"id":"f4318a833d8d5cd2","repo":"microsoft/aspire","slug":"cannot-use-null-in-a-reference-expression","errorCode":null,"errorMessage":"Cannot use null in a reference expression","messagePattern":"Cannot use null in a reference expression","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.CodeGeneration.Java/Resources/Base.java","lineNumber":255,"sourceCode":"        reqArgs.put(\"context\", AspireClient.serializeValue(handle));\n        if (cancellationToken != null) {\n            reqArgs.put(\"cancellationToken\", cancellationToken);\n        }\n\n        return (String) client.invokeCapability(\"Aspire.Hosting.ApplicationModel/getValue\", reqArgs);\n    }\n\n    public static ReferenceExpression refExpr(String format, Object... valueProviders) {\n        return new ReferenceExpression(format, valueProviders);\n    }\n\n    public static ReferenceExpression createConditional(Object condition, String matchValue, ReferenceExpression whenTrue, ReferenceExpression whenFalse) {\n        return new ReferenceExpression(condition, matchValue, whenTrue, whenFalse);\n    }\n\n    private static Object extractValueProvider(Object value) {\n        if (value == null) {\n            throw new IllegalArgumentException(\"Cannot use null in a reference expression\");\n        }\n\n        if (value instanceof String || value instanceof Number || value instanceof Boolean) {\n            return value;\n        }\n\n        return AspireClient.serializeValue(value);\n    }\n}\n\n/**\n * AspireList is a handle-backed list with lazy handle resolution.\n */\nclass AspireList<T> extends HandleWrapperBase {\n    private final String getterCapabilityId;\n    private Handle resolvedHandle;\n\n    AspireList(Handle handle, AspireClient client) {","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.CodeGeneration.Java/Resources/Base.java#L237-L273","documentation":"DistributedApplicationPipeline.AddStep enforces that pipeline step names are unique. Before creating the PipelineStep it scans _steps for the given name and throws an InvalidOperationException if a step with that name already exists, because steps are identified and ordered by name (dependency edges reference names).","triggerScenarios":"Calling AddStep twice with the same name value on one pipeline instance; a custom pipeline extension adding a well-known step (e.g. 'build' or 'publish') that the app already registered; tests like ExecuteAsync_WithComplexDependencyGraph_ExecutesInCorrectOrder that exercise AddStep collisions.","commonSituations":"Registering the same custom step in both a global callback and per-resource callbacks; library integrations that unconditionally AddStep on every builder call while the user also adds a step of that name; loop-based step registration without name suffixes.","solutions":["Use a unique name per AddStep call — prefix or suffix with the resource name in loops (e.g. $\"build-{resource.Name}\").","Check for an existing step before adding: skip registration if pipeline already contains the name, or update the existing step instead.","If an integration adds the duplicate, gate it behind a flag or add it only once at the app level.","Rename one of the colliding steps so dependency references (dependsOn/requiredBy) still point at the intended step."],"exampleFix":"// before\npipeline.AddStep(\"build\", context => ...);\npipeline.AddStep(\"build\", context => ...); // throws\n// after\npipeline.AddStep(\"build\", context => ...);\npipeline.AddStep(\"test\", context => ...);  // unique names","handlingStrategy":"validation","validationCode":"// C#: assert uniqueness before calling AddStep\nvar names = new HashSet<string>(StringComparer.Ordinal);\nvoid SafeAddStep(DistributedApplicationPipeline pipeline, string name, Func<PipelineStepContext, Task> action)\n{\n    if (!names.Add(name)) throw new InvalidOperationException($\"Duplicate pipeline step '{name}'\");\n    pipeline.AddStep(name, action);\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    pipeline.AddStep(name, action);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"has already been added to the pipeline\"))\n{\n    logger.LogWarning(ex, \"Step '{StepName}' already registered; skipping.\", name);\n}","preventionTips":["Derive step names from resource names or GUID suffixes in loops.","Centralize well-known step names in constants to avoid accidental collisions across integrations.","Before adding a step, check whether your extension already registered it earlier in the builder chain."],"tags":["pipeline","naming-conflict","aspire","duplicate"],"backgroundTag":"invalid-argument-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"}