{"record":{"id":"6a7f736679caa4e5","repo":"dagger/dagger","slug":"properties-must-be-a-map-got-t","errorCode":null,"errorMessage":"properties must be a map, got %T","messagePattern":"properties must be a map, got %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/llm_google.go","lineNumber":637,"sourceCode":"\t\t\t}\n\t\t\tschema.Required = required\n\t\tcase \"enum\":\n\t\t\tenum, err := toStringSlice(param)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to convert enum field: %w\", err)\n\t\t\t}\n\t\t\tschema.Enum = enum\n\t\t\tschema.Format = \"enum\"\n\t\t}\n\t}\n\n\treturn schema, nil\n}\n\nfunc bbiPropertiesToGenaiSchemas(param any) (map[string]*genai.Schema, error) {\n\tprops, ok := param.(map[string]any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"properties must be a map, got %T\", param)\n\t}\n\tschemas := map[string]*genai.Schema{}\n\tfor propKey, propParam := range props {\n\t\tpropParamMap, ok := propParam.(map[string]any)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"property %s must be a map, got %T\", propKey, propParam)\n\t\t}\n\t\tpropSchema, err := bbiSchemaToGenaiSchema(propParamMap)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to convert property %s: %w\", propKey, err)\n\t\t}\n\t\tschemas[propKey] = propSchema\n\t}\n\treturn schemas, nil\n}\n\nfunc toSchemaMaps(val any) ([]map[string]any, error) {\n\tswitch x := val.(type) {","sourceCodeStart":619,"sourceCodeEnd":655,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/core/llm_google.go#L619-L655","documentation":"bbiPropertiesToGenaiSchemas asserts that the \"properties\" value is a map[string]any mapping property names to schema objects. This error fires when properties is any other type (list, string, null explicitly), before per-property processing begins.","triggerScenarios":"Tool schema with properties as a non-map, e.g. \"properties\": [\"a\",\"b\"] or \"properties\": \"none\", passed from bbiSchemaToGenaiSchema's \"properties\" case during convertToolsToGenai.","commonSituations":"Schemas from tooling that emits properties as ordered lists; hand-written maps where properties was set to a placeholder; JSON Schema variants (like tuple-only schemas) that omit object properties.","solutions":["Make properties an object mapping property names to schema objects","Remove the properties key entirely if the parameter takes no properties","Pre-validate schemas with a JSON Schema validator before registering tools"],"exampleFix":"// before\n\"properties\": [\"width\", \"height\"]\n// after\n\"properties\": {\"width\": {\"type\": \"number\"}, \"height\": {\"type\": \"number\"}}","handlingStrategy":"type-guard","validationCode":"func checkProperties(s map[string]any) error {\n    p, ok := s[\"properties\"]\n    if !ok { return nil }\n    if _, isMap := p.(map[string]any); !isMap {\n        return fmt.Errorf(\"properties must be an object, got %T\", p)\n    }\n    return nil\n}","typeGuard":"func isPropsMap(v any) (map[string]any, bool) {\n    m, ok := v.(map[string]any)\n    return m, ok\n}","tryCatchPattern":"props, err := bbiPropertiesToGenaiSchemas(param)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"properties must be a map\") {\n        return fmt.Errorf(\"tool schema properties invalid: %w\", err)\n    }\n    return err\n}","preventionTips":["Always define properties as an object keyed by property name","Omit the properties key entirely for no-argument tools","Validate the whole tool schema with a JSON Schema validator at registration"],"tags":["schema","properties","type-mismatch","tool-calling"],"backgroundTag":"schema-validation-failed","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}