siyuan-note/siyuan · error

invalid trailing encrypted asset data

Error message

invalid trailing encrypted asset data

What it means

Even after content length checks pass, the function requires the reader to be exactly at EOF (one trailing read must return io.EOF). Any extra byte after the trailer yields this error, guaranteeing the decrypted file consumed the entire encrypted stream with no appended garbage.

Source

Thrown at kernel/model/crypto.go:2497

		written += int64(n)
		zeroAndClear(plainChunk)
		if writeErr != nil {
			return "", writeErr
		}
		if n != len(plainChunk) {
			return "", io.ErrShortWrite
		}
	}
	var terminator uint32
	if err = binary.Read(reader, binary.BigEndian, &terminator); err != nil {
		return "", err
	}
	if terminator != 0 || written != metadata.Size {
		return "", errors.New("invalid encrypted asset content length")
	}
	var trailing [1]byte
	if _, trailingErr := io.ReadFull(reader, trailing[:]); trailingErr != io.EOF {
		return "", errors.New("invalid trailing encrypted asset data")
	}
	return metadata.OriginalName, nil
}

// DecryptAsset 对应解密。
func DecryptAsset(boxID, diskName string, dek, ciphertext []byte) ([]byte, error) {
	plaintext, _, err := DecryptAssetWithName(boxID, diskName, dek, ciphertext)
	return plaintext, err
}

// notebookCryptoBackupPath 返回加密笔记本的独立 BoxCrypt 备份路径。
// 该文件在主 conf.json 丢失时用作"此笔记本是加密笔记本"的标识和降级恢复源。
// 与全局 NotebookCrypto 备份(<DataDir>/.siyuan/data-crypto-backup.json)配合使用,
// 全局备份存 MasterSalt/KEKVerifier,per-notebook 备份存 WrappedDEK/WrapNonce。
const notebookCryptoBackupFilename = "notebook-crypto-backup.json"

func notebookCryptoBackupPath(boxID string) string {
	return filepath.Join(util.DataDir, boxID, ".siyuan", notebookCryptoBackupFilename)

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Inspect the bytes after the trailer and remove any appended data, then retry
  2. Restore a clean copy of the asset from backup or sync
  3. Ensure the encrypting tool and reading tool use the same format version (no extra trailer fields)
  4. Re-encrypt the original plaintext if the appended bytes cannot be identified
Defensive patterns

Strategy: try-catch

Try / catch

if _, err := model.DecryptAsset(box, disk, dek, ct); err != nil {
    if strings.Contains(err.Error(), "trailing") {
        // inspect and strip appended bytes, or restore a clean copy
        return restoreCleanCopy(disk)
    }
    return err
}

Prevention

When it happens

Trigger: DecryptAssetToWriter reads one byte past the trailer; if io.ReadFull returns anything other than io.EOF (a byte, or an I/O error other than EOF), the error is returned. Caused by data concatenated after the encrypted asset (e.g. two files concatenated, or an appended signature/nonce).

Common situations: Backup scripts concatenating files; a writer version appending extra fields the reader doesn't know; copy/paste of files including extra bytes.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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