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

  1. Point the config path at an actual JSON file, not its parent directory
  2. In Docker, mount the single file (or a directory and reference the file inside it)
  3. 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

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


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/c0c7804540861475. Report an issue: GitHub.