siyuan-note/siyuan · error

invalid encrypted asset metadata size

Error message

invalid encrypted asset metadata size

What it means

Thrown by decryptAssetMetadata when the 4-byte metadata-size field (read from ciphertext[4:8]) is zero, exceeds 1 MiB (encryptedAssetMetadataMaxSize), or when 8 + metadataSize + 4 would exceed the total ciphertext length. This catches truncated, tampered, or bit-flipped asset files where the size header is inconsistent with the actual data.

Source

Thrown at kernel/model/crypto.go:2269

		}
		if err = binary.Write(ret, binary.BigEndian, uint32(len(encryptedChunk))); err != nil {
			return nil, err
		}
		ret.Write(encryptedChunk)
	}
	if err = binary.Write(ret, binary.BigEndian, uint32(0)); err != nil {
		return nil, err
	}
	return ret.Bytes(), nil
}

func decryptAssetMetadata(boxID, diskName string, dek, ciphertext []byte) (metadata *encryptedAssetMetadata, contentOffset int, err error) {
	if len(ciphertext) < 8 || !bytes.Equal(ciphertext[:4], encryptedAssetMagic) {
		return nil, 0, errors.New("invalid encrypted asset format")
	}
	metadataSize := int(binary.BigEndian.Uint32(ciphertext[4:8]))
	if metadataSize < 1 || metadataSize > encryptedAssetMetadataMaxSize || 8+metadataSize+4 > len(ciphertext) {
		return nil, 0, errors.New("invalid encrypted asset metadata size")
	}
	assetKey := util.DeriveSubKey(dek, "siyuan/asset")
	defer zeroAndClear(assetKey)
	aadPrefix := "siyuan:asset:" + boxID + ":assets/" + diskName
	plainMetadata, decryptErr := util.DecryptWithAAD(assetKey, ciphertext[8:8+metadataSize], []byte(aadPrefix+":metadata"))
	if decryptErr != nil {
		return nil, 0, decryptErr
	}
	metadata = &encryptedAssetMetadata{}
	if err = json.Unmarshal(plainMetadata, metadata); err != nil {
		return nil, 0, err
	}
	if metadata.OriginalName == "" || metadata.OriginalName == "." ||
		filepath.Base(metadata.OriginalName) != metadata.OriginalName || strings.ContainsAny(metadata.OriginalName, `/\`) {
		return nil, 0, errors.New("invalid encrypted asset original name")
	}
	if metadata.Size < 0 || metadata.Chunks == 0 {
		return nil, 0, errors.New("invalid encrypted asset content metadata")

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Restore the affected asset file from a valid backup or re-sync from a peer.
  2. Verify file integrity (size matches the notebook's asset index) before attempting decryption.
  3. If the file is unrecoverable, remove it from the assets directory to stop repeated decryption failures, and inform the user which asset was lost.
Defensive patterns

Strategy: validation

Validate before calling

// Basic integrity pre-check
if len(raw) < 12 {
    return errors.New("asset file too small to be valid")
}
metaSize := binary.BigEndian.Uint32(raw[4:8])
if metaSize < 1 || metaSize > 1048576 || 8+int(metaSize)+4 > len(raw) {
    return errors.New("asset file metadata header is inconsistent")
}

Try / catch

plain, err := DecryptAsset(boxID, diskName, dek, raw)
if err != nil {
    if strings.Contains(err.Error(), "invalid encrypted asset") {
        // log and skip this asset, or restore from backup
        logging.LogWarnf("skipping corrupted asset %s: %s", diskName, err)
        continue
    }
    return err
}

Prevention

When it happens

Trigger: DecryptAsset is called on a file that has the SYAE magic but a corrupted size field — bit rot on disk, partial write during sync, or deliberate tampering. Also possible if a non-asset SYAE-prefixed file is mistakenly fed to the asset decryptor.

Common situations: Disk corruption or bit rot on a long-lived encrypted asset. Sync was interrupted mid-transfer leaving a truncated file. Backup restore produced a file with correct magic but truncated body.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/9af0c1f04c1ce163. Report an issue: GitHub.