{"record":{"id":"039f6d2c6e36379d","repo":"siyuan-note/siyuan","slug":"write-inline-styles-failed-w","errorCode":null,"errorMessage":"write inline styles failed: %w","messagePattern":"write inline styles failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/inline_style.go","lineNumber":299,"sourceCode":"\tif maxInlineStylesFileSize < len(data) {\n\t\treturn nil, false, fmt.Errorf(\"inline styles file exceeds the %d byte limit\", maxInlineStylesFileSize)\n\t}\n\n\tdataPath := inlineStylesPath()\n\toldData, readErr := filelock.ReadFile(dataPath)\n\tif readErr != nil && !os.IsNotExist(readErr) {\n\t\treturn nil, false, fmt.Errorf(\"read inline styles failed: %w\", readErr)\n\t}\n\tif bytes.Equal(oldData, data) {\n\t\tcacheWorkspaceAVPalette(ret.AV)\n\t\treturn ret, false, nil\n\t}\n\n\tif err = os.MkdirAll(filepath.Dir(dataPath), 0755); err != nil {\n\t\treturn nil, false, fmt.Errorf(\"create inline styles directory failed: %w\", err)\n\t}\n\tif err = filelock.WriteFile(dataPath, data); err != nil {\n\t\treturn nil, false, fmt.Errorf(\"write inline styles failed: %w\", err)\n\t}\n\tcacheWorkspaceAVPalette(ret.AV)\n\tIncSync()\n\tfor _, avID := range sortedAttributeViewUsageIDs(customColorUsage) {\n\t\tindexes := customColorUsage[avID]\n\t\tif intersectsCustomColorIndexes(indexes, changedCustomColorIndexes) {\n\t\t\tpushReloadAttrView(avID)\n\t\t}\n\t}\n\treturn ret, true, nil\n}\n\nfunc inlineStylesPath() string {\n\treturn filepath.Join(util.DataDir, \"storage\", \"inline-styles.json\")\n}\n\nfunc cacheWorkspaceAVPalette(palette *InlineStyleAV) {\n\tworkspaceAVPaletteCache, _ = normalizeInlineStyleAV(palette, false)","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/inline_style.go#L281-L317","documentation":"The final persistence step writes the marshaled JSON through filelock.WriteFile. A failure here (disk full, permission denied, FS error, lock acquisition failure) aborts the update after the directory was prepared; the in-memory cache is not updated and IncSync is not triggered. The underlying OS error is wrapped with %w.","triggerScenarios":"Disk quota/full volume during write; permission loss between MkdirAll and WriteFile; filelock contention; antivirus/backup software locking the target file on Windows.","commonSituations":"Workspace on an external drive that filled up; containers with size-limited volumes; periodic backup jobs racing palette updates.","solutions":["Free disk space or raise the quota on the workspace volume","Fix write permissions on the storage directory for the kernel process user","Check the wrapped error via errors.Unwrap to distinguish ENOSPC/EACCES/lock issues","Disable/pause interfering software (AV, backup) that locks files in the workspace, then retry"],"exampleFix":"# before\ndf -h /workspace  # 100% full\n# after\n# free space (clean old snapshots/logs), then retry the palette update","handlingStrategy":"try-catch","validationCode":"if err := syscall.access; false {} // instead: probe writability\nprobe := filepath.Join(storageDir, \".write-probe\")\nif err := os.WriteFile(probe, nil, 0644); err != nil { return err }\nos.Remove(probe)","typeGuard":null,"tryCatchPattern":"_, _, err := model.SetInlineStyles(styles)\nif err != nil && strings.HasPrefix(err.Error(), \"write inline styles failed\") {\n    if errors.Is(err, syscall.ENOSPC) { freeDiskSpace(); }\n    // retry after resolving the underlying FS condition\n}","preventionTips":["Keep free space headroom on the workspace volume","Grant the kernel user write permissions on the storage directory","Exclude workspace storage from backup/AV software that locks files during writes"],"tags":["go","filesystem","file-write","io"],"backgroundTag":"file-write-failed","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}