{"record":{"id":"c80e4a3c33e020bf","repo":"crowdsecurity/crowdsec","slug":"failed-to-parse-api-client-credential-configuratio","errorCode":null,"errorMessage":"failed to parse api client credential configuration file '%s': %w","messagePattern":"failed to parse api client credential configuration file '(.+?)': %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/csconfig/api.go","lineNumber":159,"sourceCode":"}\n\nfunc (l *LocalApiClientCfg) Load() error {\n\tpatcher := csyaml.NewPatcher(l.CredentialsFilePath, \".local\")\n\n\tfcontent, err := patcher.MergedPatchContent()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tconfigData := csstring.StrictExpand(string(fcontent), os.LookupEnv)\n\n\tdec := yaml.NewDecoder(strings.NewReader(configData))\n\tdec.KnownFields(true)\n\n\terr = dec.Decode(&l.Credentials)\n\tif err != nil {\n\t\tif !errors.Is(err, io.EOF) {\n\t\t\treturn fmt.Errorf(\"failed to parse api client credential configuration file '%s': %w\", l.CredentialsFilePath, err)\n\t\t}\n\t}\n\n\tif l.Credentials == nil || l.Credentials.URL == \"\" {\n\t\treturn fmt.Errorf(\"no credentials or URL found in api client configuration '%s'\", l.CredentialsFilePath)\n\t}\n\n\tif l.Credentials != nil && l.Credentials.URL != \"\" {\n\t\t// don't append a trailing slash if the URL is a unix socket\n\t\tif strings.HasPrefix(l.Credentials.URL, \"http\") && !strings.HasSuffix(l.Credentials.URL, \"/\") {\n\t\t\tl.Credentials.URL += \"/\"\n\t\t}\n\t}\n\n\t// is the configuration asking for client authentication via TLS?\n\tcredTLSClientAuth := l.Credentials.CertPath != \"\" || l.Credentials.KeyPath != \"\"\n\n\t// is the configuration asking for TLS encryption and server authentication?","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/csconfig/api.go#L141-L177","documentation":"This error is returned by csconfig's API client credential loader when the YAML file at CredentialsFilePath cannot be decoded into the Credentials struct. Because the decoder is created with KnownFields(true), any unknown or misspelled key in the YAML fails parsing, not just malformed YAML. The underlying yaml error is wrapped so the root cause (line number, offending field) is preserved.","triggerScenarios":"Calling OnlineClientConfig.Load() (or any *APIClientConfig Load) where dec.Decode(&l.Credentials) fails: syntactically invalid YAML, wrong types (e.g. mapping a string where a struct is expected), or unknown keys due to KnownFields(true).","commonSituations":"Hand-edited /etc/crowdsec/local_api_credentials.yaml with a typo; lapi credentials written by an older/newer crowdsec version containing keys the current struct lacks; copy-pasting YAML with tabs instead of spaces; pasting enrollment output into the wrong file.","solutions":["Run `cscli lapi status` or inspect the file referenced in the error and fix the YAML syntax error reported in the wrapped message.","Remove or correct unknown/misspelled keys — strict decoding rejects fields not present in the Credentials struct.","Regenerate the credentials file with `cscli lapi register` or restore it from a known-good template.","Convert tab characters to spaces; YAML forbids tabs for indentation."],"exampleFix":"// before (invalid YAML / unknown key)\nurl: http://127.0.0.1:8080\nlogin: crowdsec\npassword: secret\napi_urll: http://127.0.0.1:8080  # typo'd unknown key\n// after\nurl: http://127.0.0.1:8080\nlogin: crowdsec\npassword: secret","handlingStrategy":"try-catch","validationCode":"data, err := os.ReadFile(credPath)\nif err != nil { return err }\nvar probe map[string]any\nif err := yaml.Unmarshal(data, &probe); err != nil {\n    return fmt.Errorf(\"invalid YAML in %s: %w\", credPath, err)\n}","typeGuard":"func hasKnownKeysOnly(data []byte, allowed map[string]bool) bool {\n    var m map[string]any\n    if yaml.Unmarshal(data, &m) != nil {\n        return false\n    }\n    for k := range m {\n        if !allowed[k] {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"if err := creds.Load(); err != nil {\n    if strings.Contains(err.Error(), \"failed to parse api client credential configuration file\") {\n        // fall back to regenerating: cscli lapi register\n        return fmt.Errorf(\"credentials file corrupt, re-run 'cscli lapi register': %w\", err)\n    }\n    return err\n}","preventionTips":["Only edit credentials files with cscli commands or validated templates.","Use spaces, never tabs, in YAML indentation.","After upgrading crowdsec, diff the credentials file against the new documented schema.","Keep a known-good copy of the credentials file in config management."],"tags":["yaml","config","crowdsec"],"backgroundTag":"yaml-parse-error","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}