siyuan-note/siyuan · error

Conf.Language(49)

Error message

Conf.Language(49)

What it means

CreateDailyNote in kernel/model/file.go:1438 reads the notebook's configured DailyNoteSavePath. If it is empty or set to the root '/', the daily-note document has no defined location, so the function returns localized kernel message 49: 'Please specify the daily note save path in the Notebook Settings'. It is a configuration precondition, not a runtime fault.

Source

Thrown at kernel/model/file.go:1438

const (
	DailyNoteAttrPrefix = "custom-dailynote-"
	NodeAttrTitleEmpty  = "custom-sy-title-empty"
	DocHiddenAttr       = "custom-hidden"
)

func CreateDailyNote(boxID string) (p string, existed bool, err error) {
	createDocLock.Lock()
	defer createDocLock.Unlock()

	box := Conf.Box(boxID)
	if nil == box {
		err = ErrBoxNotFound
		return
	}

	boxConf := box.GetConf()
	if "" == boxConf.DailyNoteSavePath || "/" == boxConf.DailyNoteSavePath {
		err = errors.New(Conf.Language(49))
		return
	}

	hPath, err := RenderGoTemplateInBox(boxConf.DailyNoteSavePath, box.ID)
	if err != nil {
		return
	}

	FlushTxQueue()

	hPath = util.TrimSpaceInPath(hPath)
	existRoot := treenode.GetBlockTreeRootByHPath(box.ID, hPath)
	if nil != existRoot {
		existed = true
		p = existRoot.Path

		tree, loadErr := LoadTreeByBlockID(existRoot.RootID)
		if nil != loadErr {

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Open the notebook's settings (right-click notebook > Settings or Settings - Collect - Notebook) and set the 'Daily note save path' to a non-root template path such as '/daily note/{{now | date "2006-01"}}/2006-01-02'.
  2. Alternatively call the API on a notebook that already has DailyNoteSavePath configured.
  3. If automating, ensure the notebook conf JSON (conf.json of the notebook) contains a non-empty, non-'/' dailynoteSavePath before invoking.

Example fix

// before: notebook conf.json has no dailynoteSavePath
POST /api/filetree/createDailyNote {"notebook": "20240101120000-abc"} // -> error 49
// after: set dailynoteSavePath = "/daily note/{{now | date \"2006-01\"}}/2006-01-02" in notebook settings, then retry
Defensive patterns

Strategy: validation

Validate before calling

const conf = await getNotebookConf(boxID);
const p = conf.conf?.dailynoteSavePath || conf.box?.dailynoteSavePath;
if (!p || p === "/") {
  throw new Error(`notebook ${boxID} has no daily note save path configured`);
}

Type guard

function hasDailyNotePath(conf) {
  return typeof conf?.dailynoteSavePath === "string" && conf.dailynoteSavePath !== "/" && conf.dailynoteSavePath.length > 0;
}

Try / catch

try {
  await createDailyNote(boxID);
} catch (e) {
  if (String(e.msg).includes("daily note save path")) {
    await setNotebookConf(boxID, {...conf, dailynoteSavePath: "/daily note/{{now | date \"2006-01\"}}/2006-01-02"});
    await createDailyNote(boxID);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Invoking CreateDailyNote (API /api/filetree/createDailyNote, or the daily-note append/prepend/prepare actions, plugins like dailynoteCreate) on a notebook whose DailyNoteSavePath was never configured, or which was cleared/set to '/' in notebook settings.

Common situations: A freshly created notebook used before opening Notebook Settings; restoring or syncing a workspace where notebook conf was lost; a plugin or script that creates a notebook programmatically and immediately tries to create its daily note; users deleting the daily-note path entry thinking '/' means 'notebook root'.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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