{"record":{"id":"6a722b115ad20957","repo":"mislav/hub","slug":"host-name-is-must-be-string-but-got-v","errorCode":null,"errorMessage":"host name is must be string but got %#v","messagePattern":"host name is must be string but got %#v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"github/config_decoder.go","lineNumber":50,"sourceCode":"\n\tyc := yaml.MapSlice{}\n\terr = yaml.Unmarshal(d, &yc)\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, hostEntry := range yc {\n\t\tv, ok := hostEntry.Value.([]interface{})\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"value of host entry is must be array but got %#v\", hostEntry.Value)\n\t\t}\n\t\tif len(v) < 1 {\n\t\t\tcontinue\n\t\t}\n\t\thostName, ok := hostEntry.Key.(string)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"host name is must be string but got %#v\", hostEntry.Key)\n\t\t}\n\t\thost := &Host{Host: hostName}\n\t\tfor _, prop := range v[0].(yaml.MapSlice) {\n\t\t\tpropName, ok := prop.Key.(string)\n\t\t\tif !ok {\n\t\t\t\treturn fmt.Errorf(\"property name is must be string but got %#v\", prop.Key)\n\t\t\t}\n\t\t\tswitch propName {\n\t\t\tcase \"user\":\n\t\t\t\thost.User, ok = prop.Value.(string)\n\t\t\tcase \"oauth_token\":\n\t\t\t\thost.AccessToken, ok = prop.Value.(string)\n\t\t\tcase \"protocol\":\n\t\t\t\thost.Protocol, ok = prop.Value.(string)\n\t\t\tcase \"unix_socket\":\n\t\t\t\thost.UnixSocket, ok = prop.Value.(string)\n\t\t\t}\n\t\t\tif !ok {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/mislav/hub/blob/5c547ed804368763064e51f3990851e267e88edd/github/config_decoder.go#L32-L68","documentation":"While decoding a host entry, the decoder casts each top-level key to a string to use as the host name. If the key is another YAML scalar type (number, boolean, null), the cast fails and this error is returned. It ensures host names in the config are proper strings.","triggerScenarios":"A configs file containing a host key that is not a string, e.g. a bare number (`12345:`) or boolean (`true:`) at top level, or YAML that parses a domain into a non-string scalar.","commonSituations":"Unquoted hostnames that YAML interprets as booleans or numbers (classic YAML Norway problem with `no:`), stray indentation turning text into a key of the wrong type.","solutions":["Quote the host key in the YAML: `\"github.example.com\":` so it always parses as a string.","Remove any non-host keys accidentally present at the top level of ~/.config/hub.","Check indentation — a misindented property may become a top-level key."],"exampleFix":"// before (parses as boolean)\nno:\n- user: octocat\n// after\n\"no.example.com\":\n- user: octocat","handlingStrategy":"validation","validationCode":"var raw map[interface{}]interface{}\nyaml.Unmarshal(data, &raw)\nfor k := range raw {\n    if _, ok := k.(string); !ok {\n        log.Fatalf(\"top-level key %v is not a string; quote it in YAML\", k)\n    }\n}","typeGuard":"func isStringKey(k interface{}) bool {\n    _, ok := k.(string)\n    return ok\n}","tryCatchPattern":"if err := cfg.Decode(data); err != nil {\n    if strings.Contains(err.Error(), \"host name is must be string\") {\n        return fmt.Errorf(\"quote non-string host keys in ~/.config/hub: %w\", err)\n    }\n    return err\n}","preventionTips":["Quote every host key (\"ghe.example.com\":) to defeat YAML scalar typing","Watch for keys that YAML reads as booleans/numbers (no, yes, 123)","Run a YAML linter on the config after manual edits"],"tags":["yaml","configuration","decoding","type-error"],"backgroundTag":"config-schema-validation-failed","analyzedSha":"5c547ed804368763064e51f3990851e267e88edd","analyzedAt":"2026-09-01T03:34:15.525Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}