siyuan-note/siyuan · error

write publishAccess.json

Error message

write publishAccess.json [%s] failed: %s

What it means

SetPublishAccess fails with this message when filelock.WriteFile cannot persist publishAccess.json after the directory was created and the JSON marshaled. The in-memory state remains updated, but the on-disk copy stays stale, so publish access settings silently revert after a restart. The message includes the file path and the underlying error.

Solutions

  1. Read the path and OS error from the kernel log, then fix permissions on <workspace>/.siyuan/publishAccess.json (chown/chmod) or free disk space
  2. Stop other SiYuan instances or sync tools that may hold the filelock, then retry
  3. If the file is corrupt/locked persistently, stop the kernel, remove it (settings are re-savable), and re-apply publish access
  4. Re-run the update after fixing so the in-memory change is persisted to disk

Example fix

# before
ls -l <workspace>/.siyuan/publishAccess.json  # root-owned, 0644
# after
chown siyuan:siyuan <workspace>/.siyuan/publishAccess.json && chmod 600 <workspace>/.siyuan/publishAccess.json
Defensive patterns

Strategy: try-catch

Validate before calling

const f = path.join(dataDir, ".siyuan", "publishAccess.json");
try { fs.accessSync(path.dirname(f), fs.constants.W_OK); } catch { throw new Error(".siyuan not writable"); }
if (fs.existsSync(f)) fs.accessSync(f, fs.constants.W_OK);

Try / catch

err := model.SetPublishAccess(access)
if err != nil {
    if strings.Contains(err.Error(), "write publishAccess.json") {
        // release file locks / fix permissions, then retry once
    }
    return err
}

Prevention

When it happens

Trigger: SetPublishAccess when the .siyuan/publishAccess.json write fails: read-only filesystem, permission denied on the existing file, another process/lock holder, antivirus locking the file, or disk full.

Common situations: File owned by a different user after running the kernel as root once; sync/backup tools (or two kernel instances) holding the file lock; Windows Defender or OneDrive temporarily locking the JSON; read-only Docker volume.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/5f72fb3cfc1119dc. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/publish_access.go:140

	err = os.MkdirAll(filepath.Dir(publishAccessPath), 0755)
	if err != nil {
		msg := fmt.Sprintf("create dir for publishAccess.json [%s] failed: %s", publishAccessPath, err)
		logging.LogError(msg)
		err = errors.New(msg)
		return
	}

	data, err := gulu.JSON.MarshalJSON(inputPublishAccess)
	if err != nil {
		logging.LogErrorf("marshal publishAccess.json [%s] failed: %s", publishAccessPath, err)
		return
	}

	err = filelock.WriteFile(publishAccessPath, data)
	if err != nil {
		msg := fmt.Sprintf("write publishAccess.json [%s] failed: %s", publishAccessPath, err)
		logging.LogError(msg)
		err = errors.New(msg)
		return
	}
	return
}

func GetInvisiblePublishAccess(inputPublishAccess PublishAccess) (outputPublishAccess PublishAccess) {
	outputPublishAccess = filterInvisiblePublishAccess(inputPublishAccess)
	outputPublishAccess = appendEncryptedBoxesToPublishAccess(outputPublishAccess)
	return
}

func filterInvisiblePublishAccess(inputPublishAccess PublishAccess) (outputPublishAccess PublishAccess) {
	outputPublishAccess = PublishAccess{}
	for _, item := range inputPublishAccess {
		if !item.Visible {
			outputPublishAccess = append(outputPublishAccess, item)
		}
	}

View on GitHub (pinned to 9f775e8a12)