siyuan-note/siyuan · error

database history ID does not match its filename

Error message

database history ID does not match its filename

What it means

After parsing a database history snapshot, the embedded attribute view ID inside the data must equal the avID derived from the history filename. A mismatch means the file does not belong to the database named by its path — usually a misnamed, copied, or mismatched history artifact — and restoring it would write foreign data into the wrong attribute view.

Solutions

  1. Locate the history file whose embedded ID matches the target avID and restore that one instead
  2. Rename nothing blindly: inspect the parsed view ID first and restore from the correct database's history list
  3. Regenerate a fresh history entry of the current database if no matching snapshot exists
  4. Report the mismatch if it arose from the built-in history writer (a naming bug)
Defensive patterns

Strategy: validation

Validate before calling

const parsed = parseAVData(data);
if (parsed.id !== avIDFromFilename(filename)) {
  throw new Error('history file does not belong to ' + avID);
}

Prevention

When it happens

Trigger: restoreAttributeView/backupBoundAttributeViewHistory where view.ID != avID, e.g. a history file renamed to another attribute view's filename, history directories merged between databases, or a bug copying history artifacts under the wrong name.

Common situations: Manual file management of the history folder; backup-restore tooling that renames files; comparing/restoring across workspaces with divergent databases.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/attribute_view_block_history.go:43

		return nil, err
	}
	if boxID != "" {
		if !util.IsCiphertext(data) {
			return nil, errors.New("encrypted database history is plaintext")
		}
		data, err = av.DecryptAVData(boxID, avID, data)
		if err != nil {
			return nil, err
		}
	} else if util.IsCiphertext(data) {
		return nil, errors.New("encrypted database history has no notebook context")
	}
	view, err := av.ParseAttributeViewData(avID, data)
	if err != nil {
		return nil, err
	}
	if view.ID != avID {
		return nil, errors.New("database history ID does not match its filename")
	}
	for _, kv := range view.KeyValues {
		if kv == nil || kv.Key == nil {
			return nil, errors.New("database history contains an invalid field")
		}
		for _, value := range kv.Values {
			if value == nil {
				return nil, errors.New("database history contains an invalid value")
			}
		}
	}
	if view.GetBlockKeyValues() == nil {
		return nil, errors.New("database history has no primary field")
	}
	for _, layout := range view.Views {
		if layout == nil {
			return nil, errors.New("database history contains an invalid view")
		}

View on GitHub (pinned to 9f775e8a12)