microsoft/aspire · error · ValueError

Cannot use None in reference expression

Error message

Cannot use None in reference expression

What it means

_extract_handle_for_expr raises ValueError('Cannot use None in reference expression') when a None value is passed where a reference-expression operand is expected. Reference expressions accept handles, string literals, or numbers; None is not a valid operand because it cannot be serialized into an expression value.

Solutions

  1. Ensure the value is resolved before building the expression; fail fast if a required resource handle is None.
  2. Substitute an explicit string literal (e.g., empty string or a default) when None is legitimately possible.
  3. Use conditional logic to skip the expression entirely when the value is absent.
  4. Check that the upstream lookup (handle acquisition) actually succeeded before composing the expression.

Example fix

// before
handle = find_resource(name)  # may be None
expr = string_expr("{h}", h=handle)
// after
handle = find_resource(name)
if handle is None:
    raise ValueError(f"resource {name!r} not found")
expr = string_expr("{h}", h=handle)
Defensive patterns

Strategy: validation

Validate before calling

def operand_or_fail(value):
    if value is None:
        raise ValueError('reference-expression operand was None; resolve resource first')
    return value

Type guard

def is_valid_operand(value) -> bool:
    return value is not None and (isinstance(value, (str, int, float)) or hasattr(value, 'handle_id'))

Try / catch

try:
    expr = string_expr('{h}', h=value)
except ValueError as e:
    if 'Cannot use None' in str(e):
        expr = string_expr('{h}', h='')
    else:
        raise

Prevention

When it happens

Trigger: Passing None as an argument to a reference-expression builder (e.g., string_expr-style composition or an API that extracts handles from values) — typically from an unassigned variable or an optional field left unset.

Common situations: A resource/endpoint lookup returned None and the result was fed into an expression; optional kwargs defaulted to None and were passed through; refactored code where a variable lost its assignment; reading config values that are missing and come back None.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/470cbc4b025cde1a. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.CodeGeneration.Python/PythonModuleBuilder.cs:1434

                        result["$expr"]["valueProviders"] = self._value_providers
                    return result
                raise ValueError("Invalid ReferenceExpression: must have either handle, condition, or format")

            def __repr__(self) -> str:
                if self._handle:
                    return f"ReferenceExpression(handle={self._handle.handle_id})"
                if self._condition:
                    return "ReferenceExpression(conditional)"
                return f"ReferenceExpression(formattedString)"


        def _extract_handle_for_expr(value: typing.Any) -> typing.Any:
            '''
            Extracts a value for use in reference expressions.
            Supports handles (objects) and string literals.
            '''
            if value is None:
                raise ValueError("Cannot use None in reference expression")

            # String literals - include directly in the expression
            if isinstance(value, str):
                return value

            # Number literals - convert to string
            if isinstance(value, (int, float)):
                return str(value)

            # Handle objects - get their JSON representation
            if isinstance(value, (Handle, _ReferenceHandle)):
                return value

            # Objects with $handle property (already in handle format)
            if isinstance(value, dict) and "$handle" in value:
                return value

            raise ValueError(

View on GitHub (pinned to 25830f84bd)