{"record":{"id":"14f84fbc9584f2b8","repo":"microsoft/aspire","slug":"cannot-use-value-of-type-type-value-name-in-reference","errorCode":null,"errorMessage":"Cannot use value of type {type(value).__name__} in reference expression. Expected a handle object, string, or number.","messagePattern":"Cannot use value of type (.+?) in reference expression\\. Expected a handle object, string, or number\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.CodeGeneration.Python/PythonModuleBuilder.cs","lineNumber":1452,"sourceCode":"                raise ValueError(\"Cannot use None in reference expression\")\n\n            # String literals - include directly in the expression\n            if isinstance(value, str):\n                return value\n\n            # Number literals - convert to string\n            if isinstance(value, (int, float)):\n                return str(value)\n\n            # Handle objects - get their JSON representation\n            if isinstance(value, (Handle, _ReferenceHandle)):\n                return value\n\n            # Objects with $handle property (already in handle format)\n            if isinstance(value, dict) and \"$handle\" in value:\n                return value\n\n            raise ValueError(\n                f\"Cannot use value of type {type(value).__name__} in reference expression. \"\n                f\"Expected a handle object, string, or number.\"\n            )\n\n\n        def string_expr(value: str, **kwargs: typing.Any) -> ReferenceExpression:\n            '''\n            Helper function for creating reference expressions with named placeholders.\n\n            Use this to create dynamic expressions that reference endpoints, parameters, and other\n            value providers. The expression is evaluated at runtime by Aspire.\n\n            Example:\n                ```python\n                redis = await builder.add_redis(\"cache\")\n                endpoint = await redis.get_endpoint(\"tcp\")\n\n                # Create a reference expression using named placeholders","sourceCodeStart":1434,"sourceCodeEnd":1470,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.CodeGeneration.Python/PythonModuleBuilder.cs#L1434-L1470","documentation":"_extract_handle_for_expr raises ValueError when a value is neither a handle object, a string, a number, nor an already-formed {'$handle': ...} dict — for example lists, booleans in unexpected positions, dicts without $handle, or arbitrary objects. Reference-expression operands must be serializable into the expression protocol, and this type is not.","triggerScenarios":"Passing a list, dict (without '$handle' key), bool, datetime, or custom object into a reference-expression argument; passing a marshalled transport dict where a raw handle was expected; feeding a parsed JSON structure directly as an operand.","commonSituations":"Accidentally passing a collection where a single handle was intended (e.g., a list of resources instead of one); passing a config dict instead of a value; passing booleans which are not accepted number-like literals here; SDK version change altering what counts as a handle.","solutions":["Pass the resource's handle object itself, not a list/dict wrapper containing it.","Convert the value to a string or number first if it is a literal (e.g., str(value) or int(value)).","Unwrap collections: pick the specific element that should participate in the expression.","If you already have a transport dict, ensure it contains the '$handle' key as the protocol expects."],"exampleFix":"// before\nexpr = string_expr(\"{r}\", r=[redis, postgres])  # list not allowed\n// after\nexpr = string_expr(\"{r}\", r=redis)  # pass the single handle","handlingStrategy":"type-guard","validationCode":"def ensure_operand(value):\n    if isinstance(value, (list, dict)) and not (isinstance(value, dict) and '$handle' in value):\n        raise TypeError(f'unsupported operand type {type(value).__name__}; pass a handle, str, or number')\n    return value","typeGuard":"def is_expression_operand(value) -> bool:\n    if value is None:\n        return False\n    if isinstance(value, (str, int, float)):\n        return True\n    if isinstance(value, dict):\n        return '$handle' in value\n    return hasattr(value, 'handle_id')","tryCatchPattern":"try:\n    expr = string_expr('{r}', r=value)\nexcept ValueError as e:\n    if 'Cannot use value of type' in str(e):\n        value = coerce_to_operand(value)  # unwrap/convert\n        expr = string_expr('{r}', r=value)\n    else:\n        raise","preventionTips":["Pass single handles, not collections of handles","Convert literals to str/int/float before composing expressions","Verify transport dicts contain the '$handle' key before reuse"],"tags":["python","reference-expression","type-error","validation"],"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-21T09:17:21.228Z"}