siyuan-note/siyuan · error

create inline styles directory failed: %w

Error message

create inline styles directory failed: %w

What it means

Before writing the new styles JSON, setInlineStylesData ensures the parent directory (under the workspace storage path) exists via os.MkdirAll. If directory creation fails (permissions, read-only FS, path is a file), the write aborts with this wrapped error.

Source

Thrown at kernel/model/inline_style.go:296

	if err != nil {
		return nil, false, fmt.Errorf("marshal inline styles failed: %w", err)
	}
	if maxInlineStylesFileSize < len(data) {
		return nil, false, fmt.Errorf("inline styles file exceeds the %d byte limit", maxInlineStylesFileSize)
	}

	dataPath := inlineStylesPath()
	oldData, readErr := filelock.ReadFile(dataPath)
	if readErr != nil && !os.IsNotExist(readErr) {
		return nil, false, fmt.Errorf("read inline styles failed: %w", readErr)
	}
	if bytes.Equal(oldData, data) {
		cacheWorkspaceAVPalette(ret.AV)
		return ret, false, nil
	}

	if err = os.MkdirAll(filepath.Dir(dataPath), 0755); err != nil {
		return nil, false, fmt.Errorf("create inline styles directory failed: %w", err)
	}
	if err = filelock.WriteFile(dataPath, data); err != nil {
		return nil, false, fmt.Errorf("write inline styles failed: %w", err)
	}
	cacheWorkspaceAVPalette(ret.AV)
	IncSync()
	for _, avID := range sortedAttributeViewUsageIDs(customColorUsage) {
		indexes := customColorUsage[avID]
		if intersectsCustomColorIndexes(indexes, changedCustomColorIndexes) {
			pushReloadAttrView(avID)
		}
	}
	return ret, true, nil
}

func inlineStylesPath() string {
	return filepath.Join(util.DataDir, "storage", "inline-styles.json")
}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Check that filepath.Dir(inlineStylesPath()) is not occupied by a regular file; remove/rename the file
  2. Grant the kernel process write permission on the workspace storage directory (chown/chmod)
  3. Remount the workspace volume read-write if it is read-only
  4. Inspect the wrapped OS error (permission denied vs no space vs not a directory) to target the fix

Example fix

# before
storage/inline_styles/  -> actually a regular file
# after
mv storage/inline_styles storage/inline_styles.bak && mkdir storage/inline_styles
Defensive patterns

Strategy: try-catch

Validate before calling

dir := filepath.Dir(stylesPath)
if fi, err := os.Stat(dir); err == nil && !fi.IsDir() {
    return fmt.Errorf("%s is not a directory", dir)
}

Try / catch

_, _, err := model.SetInlineStyles(styles)
if err != nil && strings.HasPrefix(err.Error(), "create inline styles directory failed") {
    return fmt.Errorf("check storage dir permissions/mount: %w", err)
}

Prevention

When it happens

Trigger: The target directory path exists as a regular file; the workspace volume is read-only or full; the process lacks write permission on the storage parent directory; SELinux/AppArmor denies creation.

Common situations: Docker containers with a read-only or mis-mounted workspace; a stray file named like the expected directory after a bad restore; running as non-root against a root-owned workspace.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/9913ea25bffaf817. Report an issue: GitHub.