usememos/memos · error
file must resolve to a regular file
Error message
file must resolve to a regular file
What it means
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.
Source
Thrown at store/deployment_config.go:128
identityProviders: map[string]*storepb.IdentityProvider{},
instanceSettings: map[storepb.InstanceSettingKey]*storepb.InstanceSetting{},
}
}
func isIdentityProviderDeploymentFilename(name string) bool {
// The original database-writing bootstrap accepted every filename with this
// prefix and suffix. Continue loading those names so an upgrade cannot
// silently fall back to stale credentials stored in the database.
return strings.HasPrefix(name, "memos-idp-") && strings.HasSuffix(name, ".json")
}
func readDeploymentProtoJSON(path string, message proto.Message) error {
info, err := os.Stat(path)
if err != nil {
return errors.Wrap(err, "failed to inspect file")
}
if !info.Mode().IsRegular() {
return errors.New("file must resolve to a regular file")
}
file, err := os.Open(path)
if err != nil {
return errors.Wrap(err, "failed to open file")
}
defer file.Close()
info, err = file.Stat()
if err != nil {
return errors.Wrap(err, "failed to inspect file")
}
if !info.Mode().IsRegular() {
return errors.New("file must resolve to a regular file")
}
content, err := io.ReadAll(io.LimitReader(file, maxDeploymentConfigurationSize+1))
if err != nil {
return errors.Wrap(err, "failed to read file")
}
if len(content) > maxDeploymentConfigurationSize {View on GitHub (pinned to 14d757ce1f)
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
Example fix
# before -v ./idp:/var/opt/memos/idp.json # mounts a directory as the "file" # after -v ./idp/memos-idp-oauth.json:/var/opt/memos/idp/memos-idp-oauth.json
Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(path)
if err != nil {
return err
}
if !info.Mode().IsRegular() {
return fmt.Errorf("config path %s is not a regular file", path)
} Prevention
- Mount the config file itself, not its directory, when passing it to containers
- Run stat on bootstrap paths in deployment scripts before app start
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- unknown db driver
- failed to decode protobuf JSON; verify field names, value ty
- id must be omitted
- uid is invalid
- name is required
AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15).
Data as JSON: /api/errors/c0c7804540861475.
Report an issue: GitHub.