{"record":{"id":"2cbb93f9997d9d8b","repo":"unoplatform/uno","slug":"the-staged-content-was-released-when-the-download","errorCode":null,"errorMessage":"The staged content was released when the download was triggered.","messagePattern":"The staged content was released when the download was triggered\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Uno.UWP/ts/Windows/Storage/Streams/NativeChunkedBuffer.ts","lineNumber":258,"sourceCode":"\t\t\t\tremaining -= n;\n\t\t\t}\n\t\t\treturn new Blob(parts);\n\t\t}\n\n\t\tprivate static async tryGetDownloadDirectoryAsync(): Promise<FileSystemDirectoryHandle> {\n\t\t\ttry {\n\t\t\t\tconst root = await navigator.storage.getDirectory();\n\t\t\t\treturn await root.getDirectoryHandle(NativeChunkedBuffer.DownloadFolderName, { create: true });\n\t\t\t}\n\t\t\tcatch (e) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\n\t\tprivate throwIfReleased(): void {\n\t\t\tif (this._released) {\n\t\t\t\tthrow new Error(\"The staged content was released when the download was triggered.\");\n\t\t\t}\n\t\t}\n\n\t\tprivate ensureCapacity(bytes: number): void {\n\t\t\tconst chunkSize = NativeChunkedBuffer._chunkSize;\n\t\t\tconst requiredChunks = Math.ceil(bytes / chunkSize);\n\t\t\twhile (this._chunks.length < requiredChunks) {\n\t\t\t\tthis._chunks.push(new Uint8Array(chunkSize));\n\t\t\t}\n\t\t}\n\t}\n}\n","sourceCodeStart":240,"sourceCodeEnd":271,"githubUrl":"https://github.com/unoplatform/uno/blob/04183404888ea21b4e5bfa3493e8d5f15e972c3a/src/Uno.UWP/ts/Windows/Storage/Streams/NativeChunkedBuffer.ts#L240-L271","documentation":"Thrown by NativeChunkedBuffer.throwIfReleased when _released is true. The buffer is released (line 158) inside the download trigger flow after its chunks have been written to a Blob or OPFS file and a download URL created. Once released, the buffer's content has been handed off and any further write/read is invalid — the internal _chunks array has been cleared.","triggerScenarios":"Calling any write or append method on the NativeChunkedBuffer after triggerDownload has already executed (which sets _released = true and clears _chunks), or attempting a second download from the same buffer instance.","commonSituations":"Reusing the same IOutputStream/buffer for multiple downloads without creating a new buffer; a race where data is still being written when the download is triggered; calling WriteAsync after the stream was closed and the download fired.","solutions":["Do not write to or re-download from a buffer after triggerDownload has been called — create a new buffer for each download.","Ensure all data is fully written before invoking the download trigger.","Check the buffer lifecycle: if the managed code closes the stream before the download, sequence the operations so writes complete first."],"exampleFix":"// before: reuse buffer after download\nbuffer.triggerDownload('file.bin');\nbuffer.write(data); // _released === true → throws\n\n// after: create a new buffer for each download\nbuffer.triggerDownload('file.bin');\nconst next = new NativeChunkedBuffer();\nnext.write(data);","handlingStrategy":"validation","validationCode":"// Before writing, check the buffer hasn't been released by a download\nif ((buffer as any)._released) {\n    // create a new buffer instead of writing to a released one\n    return new NativeChunkedBuffer();\n}","typeGuard":null,"tryCatchPattern":"try {\n    buffer.write(data);\n} catch (e) {\n    if (e.message.includes('released')) {\n        // download already triggered — create a new buffer\n    } else { throw e; }\n}","preventionTips":["Treat each NativeChunkedBuffer as single-use: one write phase, one download.","Complete all writes before calling the download trigger.","Create a fresh buffer instance for each new download operation."],"tags":["wasm","storage","streams","download","lifecycle","typescript"],"backgroundTag":null,"analyzedSha":"04183404888ea21b4e5bfa3493e8d5f15e972c3a","analyzedAt":"2026-08-13T21:08:11.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}