siyuan-note/siyuan · error

invalid encrypted asset chunk count

Error message

invalid encrypted asset chunk count

What it means

decryptAssetMetadata recomputes the expected chunk count from metadata.Size (ceil division by encryptedAssetChunkSize) and requires it to equal metadata.Chunks. A mismatch means the chunk bookkeeping disagrees with the declared content size, so the container layout cannot be trusted.

Source

Thrown at kernel/model/crypto.go:2358

	// 仅认证元数据同时缺少两个版本字段时按旧容器读取,显式空值或不完整的新格式不能降级。
	if len(version.Spec) == 0 && len(version.ContainerID) == 0 {
		metadata.Spec = encryptedAssetLegacySpec
	} else if metadata.Spec != encryptedAssetSpec || len(metadata.ContainerID) != encryptedAssetContainerIDSize {
		return nil, errors.New("unsupported encrypted asset container version")
	}
	if metadata.OriginalName == "" || metadata.OriginalName == "." ||
		filepath.Base(metadata.OriginalName) != metadata.OriginalName || strings.ContainsAny(metadata.OriginalName, `/\`) {
		return nil, errors.New("invalid encrypted asset original name")
	}
	if metadata.Size < 0 {
		return nil, errors.New("invalid encrypted asset content metadata")
	}
	chunks := uint64(metadata.Size) / encryptedAssetChunkSize
	if metadata.Size%encryptedAssetChunkSize != 0 || metadata.Size == 0 {
		chunks++
	}
	if metadata.Chunks != chunks {
		return nil, errors.New("invalid encrypted asset chunk count")
	}
	return metadata, nil
}

// DecryptAssetWithName 解密资源内容并返回原始名称。
func DecryptAssetWithName(boxID, diskName string, dek, ciphertext []byte) (plaintext []byte, originalName string, err error) {
	var output bytes.Buffer
	originalName, err = DecryptAssetToWriter(boxID, diskName, dek, bytes.NewReader(ciphertext), &output)
	if err != nil {
		return nil, "", err
	}
	return output.Bytes(), originalName, nil
}

// DecryptAssetName 只解密资源的名称元数据,不处理资源内容。
func DecryptAssetName(boxID, diskName string, dek, ciphertext []byte) (originalName string, err error) {
	metadata, _, err := decryptAssetMetadata(boxID, diskName, dek, ciphertext)
	if err != nil {

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Re-encrypt the asset with the current kernel so Size and Chunks are recomputed consistently
  2. Verify the writer and reader use the same encryptedAssetChunkSize
  3. Restore the asset from a backup taken with the matching format version
  4. If a version change caused this, migrate assets by decrypt+re-encrypt before switching chunk size

Example fix

// before: chunks counted with a hardcoded size
meta.Chunks = uint64(math.Ceil(float64(size) / (1 << 20)))
// after: use the shared constant
meta.Chunks = uint64(size) / encryptedAssetChunkSize
if size%encryptedAssetChunkSize != 0 { meta.Chunks++ }
Defensive patterns

Strategy: validation

Validate before calling

expectedChunks := uint64(size) / encryptedAssetChunkSize
if size%encryptedAssetChunkSize != 0 || size == 0 { expectedChunks++ }
if meta.Chunks != expectedChunks {
    return errors.New("chunk count mismatch; re-encrypt the asset")
}

Try / catch

if err != nil && strings.Contains(err.Error(), "chunk count") {
    // re-encrypt from source or restore from a matching-version backup
}

Prevention

When it happens

Trigger: Decrypting a container where the Chunks field was computed with different chunking rules (e.g. different encryptedAssetChunkSize) than the reader, or where Size/Chunks disagree due to corruption or a buggy writer.

Common situations: Containers produced by a different version where chunk size changed, third-party generators miscounting chunks, corrupted metadata fields after storage damage.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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