{"record":{"id":"d2be117dd0c8a36e","repo":"semaphoreui/semaphore","slug":"expected-bool-for-field-got-t","errorCode":null,"errorMessage":"expected bool for field, got %T","messagePattern":"expected bool for field, got %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"services/project/backup_marshal.go","lineNumber":119,"sourceCode":"\t\t\tresult[mapKey] = mapValue\n\t\t}\n\t\treturn result, nil\n\t}\n\n\t// Handle other types (int, string, etc.)\n\treturn v.Interface(), nil\n}\n\nfunc setBasicType(data any, v reflect.Value) error {\n\tif !v.CanSet() {\n\t\treturn fmt.Errorf(\"cannot set value\")\n\t}\n\n\tswitch v.Kind() {\n\tcase reflect.Bool:\n\t\tb, ok := data.(bool)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected bool for field, got %T\", data)\n\t\t}\n\t\tv.SetBool(b)\n\tcase reflect.String:\n\t\ts, ok := data.(string)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected string for field, got %T\", data)\n\t\t}\n\t\tv.SetString(s)\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\tn, ok := toFloat64(data)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected number for field, got %T\", data)\n\t\t}\n\t\tv.SetInt(int64(n))\n\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\tn, ok := toFloat64(data)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected number for field, got %T\", data)","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/semaphoreui/semaphore/blob/1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa/services/project/backup_marshal.go#L101-L137","documentation":"Inside setBasicType (services/project/backup_marshal.go:119), when the destination field's reflect.Kind is Bool, the incoming JSON data must be a Go bool (JSON true/false). If data is any other type (string, number, null, map), the function returns \"expected bool for field, got %T\" naming the actual Go type received. It exists to prevent reflect panics from SetBool on non-bool data.","triggerScenarios":"unmarshalValueWithBackupTags encounters a backup-tagged bool struct field whose JSON value is not a boolean - e.g. a string \"true\", the number 1, or null from the backup file.","commonSituations":"Hand-edited backup JSON where a boolean field was written as \"true\" (string) or 1; backups exported from older/newer schema versions where a field changed from int to bool; JSON produced by another tool that serializes booleans as strings.","solutions":["Open the backup JSON, find the field, and change its value to a real JSON boolean (true/false, unquoted).","If the field is genuinely numeric in your data, change the Go struct field type to match (int/float) instead of bool.","Pre-validate the backup file (jq -e '... | type == \"boolean\"') before running the restore.","Re-export the backup with a compatible version of the tool so types match the current struct definitions."],"exampleFix":"// before (backup.json)\n\"allow_pprof\": \"true\"\n// after\n\"allow_pprof\": true","handlingStrategy":"validation","validationCode":"// before restore, check field type\nvar raw map[string]any\njson.Unmarshal(backupData, &raw)\nif v, ok := raw[\"allow_pprof\"]; ok {\n    if _, ok := v.(bool); !ok { return fmt.Errorf(\"field allow_pprof must be bool, got %T\", v) }\n}","typeGuard":"func isBool(v any) bool { _, ok := v.(bool); return ok }","tryCatchPattern":"if err := project.Unmarshal(data, &target); err != nil {\n    var te *project.TypeError // or inspect message\n    if strings.Contains(err.Error(), \"expected bool for field\") {\n        return fmt.Errorf(\"invalid backup: %w\", err)\n    }\n    return err\n}","preventionTips":["Write real JSON booleans (true/false), never \"true\"/1.","Validate backups against a JSON schema before restoring.","Keep export and import tool versions in sync."],"tags":["go","json","unmarshal","type-mismatch","bool"],"backgroundTag":"type-mismatch","analyzedSha":"1774ccb71a0a8b82eb74ea24c23ac9ab713de2fa","analyzedAt":"2026-09-07T11:00:33.293Z","contentChangedAt":"2026-09-07T11:00:33.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}