{"record":{"id":"93f092e02fa70761","repo":"microsoft/aspire","slug":"invalid-type-for-option-optionname-expected-string-join-or","errorCode":null,"errorMessage":"Invalid type for option '{optionName}'. Expected: {String.Join(\" or \", variations.Select(v => v.OptionType.Replace(\"typing.\", \"\")))}","messagePattern":"Invalid type for option '(.+?)'\\. Expected: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.CodeGeneration.Python/AtsPythonCodeGenerator.cs","lineNumber":2773,"sourceCode":"                builder.AppendLine(CultureInfo.InvariantCulture, $\"                rpc_args[\\\"{param.Name}\\\"] = {paramHandler}\");\n            }\n            builder.AppendLine(CultureInfo.InvariantCulture, $\"                handle = self._wrap_builder(client.invoke_capability('{variationCapabilityId}', rpc_args))\");\n        }\n        else // Single parameter\n        {\n            builder.AppendLine(CultureInfo.InvariantCulture, $\"            {clause} _validate_type(_{optionName}, {currentOption}):\");\n            builder.AppendLine(CultureInfo.InvariantCulture, $\"                rpc_args: dict[str, typing.Any] = {{\\\"{targetParamName}\\\": handle}}\");\n            var singleParam = requiredParameters.Count > 0\n                ? requiredParameters[0]\n                : optionalParameters[0];\n            var paramHandler = GetConstructorParamHandler(singleParam, $\"typing.cast({currentOption}, _{optionName})\");\n            builder.AppendLine(CultureInfo.InvariantCulture, $\"                rpc_args[\\\"{singleParam.Name}\\\"] = {paramHandler}\");\n            builder.AppendLine(CultureInfo.InvariantCulture, $\"                handle = self._wrap_builder(client.invoke_capability('{variationCapabilityId}', rpc_args))\");\n        }\n        if (last)\n        {\n            builder.AppendLine(CultureInfo.InvariantCulture, $\"            else:\");\n            builder.AppendLine(CultureInfo.InvariantCulture, $\"                raise TypeError(\\\"Invalid type for option '{optionName}'. Expected: {String.Join(\" or \", variations.Select(v => v.OptionType.Replace(\"typing.\", \"\")))}\\\")\");\n        }\n        else\n        {\n            BuildOptionConstructor(builder, capability, optionName, variations, mergedDispatch, optionIndex + 1);\n        }\n\n    }\n\n    /// <summary>\n    /// Generates a callback type signature for Python.\n    /// </summary>\n    private string GenerateCallbackTypeSignature(IReadOnlyList<AtsCallbackParameterInfo>? parameters, AtsTypeRef? returnType)\n    {\n        var paramTypes = parameters?.Select(p => MapTypeRefToPython(p.Type)).ToList() ?? [];\n        var returnTypeStr = returnType != null ? MapTypeRefToPython(returnType) : \"None\";\n\n        if (paramTypes.Count == 0)\n        {","sourceCodeStart":2755,"sourceCodeEnd":2791,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.CodeGeneration.Python/AtsPythonCodeGenerator.cs#L2755-L2791","documentation":"This TypeError is raised by generated Python builder overloads when the argument passed for a positional option (e.g. the value feeding an option-style capability variant) does not match any of the accepted variation types for that option. The generator emits a chain of isinstance-based branches, and this is the terminal `else` branch reached when none matched. The expected type names are derived from the ATS variation metadata, so the message lists the exact accepted types.","triggerScenarios":"Calling a generated option-constructor function (e.g. a builder variant selected by optionIndex) and passing a value whose runtime type is not one of the declared variation types, e.g. passing a raw string where a typed option wrapper is expected, or passing int where 'str or bool' is accepted.","commonSituations":"Hand-editing generated calls; using dynamic data (parsed JSON, env vars) whose type differs from the declared option type; Python 2/str-vs-bytes or int/float mismatches; upgrading the source package so an option's allowed types changed while call sites were not updated.","solutions":["Read the 'Expected: ...' list in the message and convert the argument to one of the listed types (e.g. str(...), int(...), or the documented option wrapper type).","Check the generated signature/docs for the option to confirm which wrapper or primitive types are accepted.","If the value comes from dynamic input, add an explicit validation/conversion step before the call.","Regenerate the Python module if the source contract changed so variants and call sites are consistent."],"exampleFix":"// before\nopts = builder.with_option(config_value)  # config_value came from JSON as int\n\n// after\nopts = builder.with_option(str(config_value))  # expected type is str","handlingStrategy":"type-guard","validationCode":"if not isinstance(config_value, (str, bool)):\n    config_value = str(config_value)\nbuilder.with_option(config_value)","typeGuard":"def is_valid_option(value, accepted=(str, bool)):\n    return isinstance(value, accepted)","tryCatchPattern":"try:\n    result = builder.with_option(value)\nexcept TypeError as e:\n    log.error(\"option type rejected: %s\", e)\n    raise","preventionTips":["Coerce dynamic (JSON/env) inputs to declared types before calling generated constructors.","Read the generated function signature/docs for each option's accepted types.","Regenerate the module whenever the source contract changes."],"tags":["type-mismatch","python","codegen","arguments"],"backgroundTag":"type-mismatch","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"}