{"record":{"id":"c0c7804540861475","repo":"usememos/memos","slug":"file-must-resolve-to-a-regular-file","errorCode":null,"errorMessage":"file must resolve to a regular file","messagePattern":"file must resolve to a regular file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"store/deployment_config.go","lineNumber":128,"sourceCode":"\t\tidentityProviders: map[string]*storepb.IdentityProvider{},\n\t\tinstanceSettings:  map[storepb.InstanceSettingKey]*storepb.InstanceSetting{},\n\t}\n}\n\nfunc isIdentityProviderDeploymentFilename(name string) bool {\n\t// The original database-writing bootstrap accepted every filename with this\n\t// prefix and suffix. Continue loading those names so an upgrade cannot\n\t// silently fall back to stale credentials stored in the database.\n\treturn strings.HasPrefix(name, \"memos-idp-\") && strings.HasSuffix(name, \".json\")\n}\n\nfunc readDeploymentProtoJSON(path string, message proto.Message) error {\n\tinfo, err := os.Stat(path)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to inspect file\")\n\t}\n\tif !info.Mode().IsRegular() {\n\t\treturn errors.New(\"file must resolve to a regular file\")\n\t}\n\tfile, err := os.Open(path)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to open file\")\n\t}\n\tdefer file.Close()\n\tinfo, err = file.Stat()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to inspect file\")\n\t}\n\tif !info.Mode().IsRegular() {\n\t\treturn errors.New(\"file must resolve to a regular file\")\n\t}\n\tcontent, err := io.ReadAll(io.LimitReader(file, maxDeploymentConfigurationSize+1))\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to read file\")\n\t}\n\tif len(content) > maxDeploymentConfigurationSize {","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/store/deployment_config.go#L110-L146","documentation":"readDeploymentProtoJSON stats the bootstrap file path before opening; if it resolves to anything other than a regular file (directory, device, socket, symlink-to-dir) it returns \"file must resolve to a regular file\". This guards deployment-config loading (e.g. memos-idp-*.json identity provider files) from reading odd filesystem objects.","triggerScenarios":"Passing a directory or /dev/stdin-style path as the deployment config file; a symlink chain ending in a directory; a fifo created by tooling where the JSON file was expected.","commonSituations":"Container mounts pointing at a directory instead of a file; config generators that create a directory named like the file; copy-paste errors in the --data bootstrap path.","solutions":["Point the config path at an actual JSON file, not its parent directory","In Docker, mount the single file (or a directory and reference the file inside it)","Run stat <path> to confirm regular-file mode before startup"],"exampleFix":"# before\n-v ./idp:/var/opt/memos/idp.json # mounts a directory as the \"file\"\n# after\n-v ./idp/memos-idp-oauth.json:/var/opt/memos/idp/memos-idp-oauth.json","handlingStrategy":"validation","validationCode":"info, err := os.Stat(path)\nif err != nil {\n    return err\n}\nif !info.Mode().IsRegular() {\n    return fmt.Errorf(\"config path %s is not a regular file\", path)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Mount the config file itself, not its directory, when passing it to containers","Run stat on bootstrap paths in deployment scripts before app start"],"tags":["deployment","configuration","filesystem","startup"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}