{"record":{"id":"40d9907a5fb80c05","repo":"charmbracelet/crush","slug":"unsupported-api-key-type-t","errorCode":null,"errorMessage":"unsupported api key type %T","messagePattern":"unsupported api key type %T","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/config.go","lineNumber":108,"sourceCode":"\tcase string:\n\t\tkind = proto.APIKeyKindString\n\t\tb, err := json.Marshal(v)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to marshal api key string: %w\", err)\n\t\t}\n\t\traw = b\n\tcase *oauth.Token:\n\t\tif v == nil {\n\t\t\treturn fmt.Errorf(\"oauth token is nil\")\n\t\t}\n\t\tkind = proto.APIKeyKindOAuth\n\t\tb, err := json.Marshal(v)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to marshal oauth token: %w\", err)\n\t\t}\n\t\traw = b\n\tdefault:\n\t\treturn fmt.Errorf(\"unsupported api key type %T\", apiKey)\n\t}\n\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/config/provider-key\", id), nil, jsonBody(proto.ConfigProviderKeyRequest{\n\t\tScope:      scope,\n\t\tProviderID: providerID,\n\t\tKind:       kind,\n\t\tAPIKey:     raw,\n\t}), http.Header{\"Content-Type\": []string{\"application/json\"}})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to set provider API key: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"failed to set provider API key: status code %d\", rsp.StatusCode)\n\t}\n\treturn nil\n}\n","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/config.go#L90-L126","documentation":"SetProviderAPIKey only accepts string or *oauth.Token API keys. Any other type (int, []byte, custom struct, untyped nil interface) hits the default branch and is rejected locally before any HTTP request is made, with the offending type printed via %T.","triggerScenarios":"Calling SetProviderAPIKey with apiKey of any type other than string or *oauth.Token, e.g. passing []byte(key), a keyring handle, or a bare nil interface.","commonSituations":"Refactored code after a version change where the signature narrowed to string | *oauth.Token; reading a key from a store that returns []byte; passing nil interface directly.","solutions":["Convert the credential: string(byteKey) for []byte values","Load an *oauth.Token for OAuth providers before calling","Check the error's %T suffix to see which type was actually passed"],"exampleFix":"// before\nkey := cfg.GetProviderKeyBytes(providerID) // []byte\nclient.SetProviderAPIKey(ctx, wsID, scope, providerID, key)\n// after\nclient.SetProviderAPIKey(ctx, wsID, scope, providerID, string(key))","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func normalizeAPIKey(key any) (any, bool) {\n    switch v := key.(type) {\n    case string:\n        return v, true\n    case *oauth.Token:\n        return v, v != nil\n    case []byte:\n        return string(v), true\n    default:\n        return nil, false\n    }\n}","tryCatchPattern":null,"preventionTips":["Only pass string or *oauth.Token to SetProviderAPIKey","Convert []byte keys with string() before calling","Check the %T suffix in the error message to identify wrong call sites"],"tags":["type-error","validation","api-key"],"backgroundTag":"unsupported-credential-type","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}