{"record":{"id":"8f5b9850b426990b","repo":"kataras/iris","slug":"malformed-document-file","errorCode":null,"errorMessage":"malformed document file: ","messagePattern":"malformed document file: ","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/basicauth/user.go","lineNumber":199,"sourceCode":"\t}\n\n\tif len(usernamePassword) > 0 {\n\t\t// JSON Form: { \"$username\":\"$pass\", \"$username\": \"$pass\" }\n\t\t// YAML Form: $username: $pass\n\t\t// \t\t\t  $username: $pass\n\t\treturn userMap(usernamePassword, opts...)\n\t}\n\n\tif len(userList) > 0 {\n\t\t// JSON Form: [{\"username\": \"$username\", \"password\": \"$pass\", \"other_field\": ...}, {\"username\": ...}, ... ]\n\t\t// YAML Form:\n\t\t// - username: $username\n\t\t//   password: $password\n\t\t//   other_field: ...\n\t\treturn AllowUsers(userList, opts...)\n\t}\n\n\tpanic(\"malformed document file: \" + jsonOrYamlFilename)\n}\n\nfunc decodeFile(src string, dest ...any) error {\n\tdata, err := ReadFile(src)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// We use unmarshal instead of file decoder\n\t// as we may need to read it more than once (dests, see below).\n\tvar (\n\t\tunmarshal func(data []byte, v any) error\n\t\text       string\n\t)\n\n\tif idx := strings.LastIndexByte(src, '.'); idx > 0 {\n\t\text = src[idx:]\n\t}","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/middleware/basicauth/user.go#L181-L217","documentation":"After decoding, AllowUsersFile expects the document to be either a username->password map or a list of objects each containing username/password fields. If neither decoded structure has entries, it panics with 'malformed document file'. The file parsed successfully but its shape does not match any supported form.","triggerScenarios":"Loading a users file whose top level is a JSON array of strings, a YAML document with neither map nor list form, or whose entries lack usable username/password keys (all entries skipped by extractUsernameAndPassword), or an empty file.","commonSituations":"Hand-edited YAML where fields were renamed (user/name instead of username/password); a file that only holds bcrypt hashes without usernames; an empty placeholder file committed to the repo.","solutions":["Reshape the file to {\"username\":\"password\", ...} or a YAML list of {username: ..., password: ...} entries.","Ensure every entry has keys extractable as username and password (check exact key names and casing).","If fields differ, decode the file yourself into structs with Username/Password fields and pass the slice to AllowUsers instead."],"exampleFix":"// before (users.yml)\naccounts:\n  - name: admin\n    secret: pass\n// after (users.yml)\n- username: admin\n  password: pass","handlingStrategy":"validation","validationCode":"var check struct {\n    Users []map[string]any `yaml:\"users\" json:\"users\"`\n}\ndata, _ := os.ReadFile(path)\nif err := yaml.Unmarshal(data, &check); err != nil || len(check.Users) == 0 {\n    // also try flat map form before failing\n    var m map[string]string\n    if err2 := yaml.Unmarshal(data, &m); err2 != nil || len(m) == 0 {\n        return errors.New(\"users file has no recognizable username/password entries\")\n    }\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Fatalf(\"basicauth users file malformed: %v\", r)\n    }\n}()\nh := basicauth.Load(\"users.yml\")","preventionTips":["Keep entries in the documented shapes: flat username:password map or a list with username/password keys.","Write a CI test that parses the real users file with AllowUsersFile semantics.","Never commit empty placeholder users files."],"tags":["go","panic","basicauth","schema-validation","yaml"],"backgroundTag":"schema-validation-failed","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}