{"record":{"id":"525712f22b3dea59","repo":"stride3d/stride","slug":"invalid-storage-offset","errorCode":null,"errorMessage":"Invalid storage offset.","messagePattern":"Invalid storage offset\\.","errorType":"exception","errorClass":"ContentStreamingException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.Serialization/Streaming/ContentStorage.cs","lineNumber":196,"sourceCode":"        for (int i = 0; i < chunksCount; i++)\n        {\n            int chunkIndex = chunksOrder[i];\n            int size = chunksData[chunkIndex].Length;\n            header.Chunks[chunkIndex].Location = offset;\n            header.Chunks[chunkIndex].Size = size;\n            offset += size;\n        }\n\n        // Create file with a raw data\n        using var outputStream = contentManager.FileProvider.OpenStream(dataUrl, VirtualFileMode.Create, VirtualFileAccess.Write, VirtualFileShare.Read, StreamFlags.Seekable);\n        using var stream = new BinaryWriter(outputStream);\n        // Write data (one after another)\n        for (int i = 0; i < chunksCount; i++)\n            stream.Write(chunksData[chunksOrder[i]]);\n\n        // Validate calculated offset\n        if (offset != outputStream.Position)\n            throw new ContentStreamingException(\"Invalid storage offset.\");\n    }\n\n    /// <inheritdoc/>\n    public sealed override int GetHashCode()\n    {\n        unchecked\n        {\n            int hashCode = (int)PackageTime.Ticks;\n            hashCode = (hashCode * 397) ^ chunks.Length;\n            for (int i = 0; i < chunks.Length; i++)\n                hashCode = (hashCode * 397) ^ chunks[i].Size;\n            return hashCode;\n        }\n    }\n\n    /// <inheritdoc/>\n    protected override void Destroy()\n    {","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.Serialization/Streaming/ContentStorage.cs#L178-L214","documentation":"ContentStorage.Create serializes chunks into a new storage stream, tracking the expected cumulative offset. After writing all chunks it compares the computed offset with outputStream.Position; a mismatch means the stream position advanced unexpectedly (chunk wrote wrong byte count or the stream is misbehaving), producing an internally inconsistent bundle.","triggerScenarios":"Writing chunks whose serialized size differs from their recorded Size; passing a non-seekable or externally advanced output stream; concurrent writes to the same stream during bundle creation.","commonSituations":"Custom chunk writers updating stream position outside Create; writing bundles to streams shared with other writers (e.g. a log-wrapped stream that injects bytes); bugs in custom IChunk data serialization.","solutions":["Ensure each chunk's Write emits exactly its recorded Size bytes to the stream.","Pass a dedicated, exclusive, seekable output stream to Create and don't touch it during creation.","Compute chunk sizes/offsets before writing and keep them consistent with actual written bytes."],"exampleFix":"// before\nusing (var shared = File.OpenWrite(path)) // also used elsewhere\n    storage.Create(shared);\n// after\nusing (var dedicated = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))\n    storage.Create(dedicated);","handlingStrategy":"try-catch","validationCode":"// verify each chunk's declared size matches its data before Create\nforeach (var c in chunks)\n    if (c.Size != GetSerializedLength(c.Data))\n        throw new InvalidOperationException(\"Chunk size mismatch before packaging\");","typeGuard":null,"tryCatchPattern":"try { storage.Create(outputStream); }\ncatch (ContentStreamingException ex) when (ex.Message == \"Invalid storage offset.\") {\n    logger.Error(\"Bundle serialization desynced; discard partial output and re-create.\");\n    outputStream.SetLength(0);\n}","preventionTips":["Use a dedicated exclusive output stream for bundle creation","Ensure chunk writers emit exactly the declared byte counts","Never share or wrap the output stream with position-altering writers"],"tags":["serialization","content","bundle","offset"],"backgroundTag":"internal-invariant-violation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}