{"record":{"id":"602cefa91070e4df","repo":"abpframework/abp","slug":"the-length-of-the-stream-is-not-available","errorCode":null,"errorMessage":"The length of the stream is not available!","messagePattern":"The length of the stream is not available!","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"warning","filePath":"framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/LeaveOpenStreamWrapper.cs","lineNumber":38,"sourceCode":"\n    public override bool CanRead => _inner.CanRead;\n    public override bool CanSeek => _inner.CanSeek;\n    public override bool CanWrite => false;\n\n    // The SDK computes the optional content length from Length/Position, but only\n    // handles NotSupportedException; translate an IOException of a probe, so an\n    // unknown length stays \"unknown\" instead of failing the upload\n    public override long Length\n    {\n        get\n        {\n            try\n            {\n                return _inner.Length;\n            }\n            catch (IOException ex)\n            {\n                throw new NotSupportedException(\"The length of the stream is not available!\", ex);\n            }\n        }\n    }\n\n    public override long Position\n    {\n        get\n        {\n            try\n            {\n                return _inner.Position;\n            }\n            catch (IOException ex)\n            {\n                throw new NotSupportedException(\"The position of the stream is not available!\", ex);\n            }\n        }\n        set => _inner.Position = value;","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/abpframework/abp/blob/7ed43b1931b9df46a50c0c59148a18645641d0df/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/LeaveOpenStreamWrapper.cs#L20-L56","documentation":"LeaveOpenStreamWrapper.Length re-throws an IOException from the inner stream as a NotSupportedException with the message 'The length of the stream is not available!'. This is an intentional translation: the AWS SDK's multipart path probes Length but only catches NotSupportedException, so converting an IOException probe failure lets the upload proceed with an 'unknown length' instead of failing. The original IOException is preserved as the InnerException.","triggerScenarios":"The AWS blob provider wraps the source BlobStream in LeaveOpenStreamWrapper; when the SDK reads the Length property and the inner stream throws IOException (e.g. a network-backed or non-seekable stream whose Length is not supported), the wrapper translates it. The SDK then treats the length as unknown and continues.","commonSituations":"Saving from a forward-only network stream, an unbuffered HTTP request body, or a stream whose Length accessor genuinely throws IOException. Normally benign (the upload continues), but it surfaces if consumer code outside the SDK reads Length directly.","solutions":["If you control the source, buffer it into a MemoryStream first so Length is always available.","Allow the SDK to continue with unknown length (this translation exists precisely for that) unless the exception escapes the SDK path.","Ensure the source stream is seekable when deterministic content length is required for the upload."],"exampleFix":"// before (length probe can throw)\nawait container.SaveAsync(name, networkStream);\n\n// after (buffer so Length is reliable)\nusing var buffer = new MemoryStream();\nawait networkStream.CopyToAsync(buffer);\nbuffer.Position = 0;\nawait container.SaveAsync(name, buffer);","handlingStrategy":"fallback","validationCode":"Stream uploadStream = sourceStream;\nif (!sourceStream.CanSeek)\n{\n    using var buffer = new MemoryStream();\n    await sourceStream.CopyToAsync(buffer);\n    buffer.Position = 0;\n    uploadStream = buffer;\n}\nawait container.SaveAsync(name, uploadStream);","typeGuard":"bool lengthAvailable = sourceStream.CanSeek; // seekable streams reliably report Length","tryCatchPattern":"// The wrapper intentionally translates IOException->NotSupportedException so the SDK\n// continues with unknown length. If it escapes, buffer the source and retry:\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"length of the stream\"))\n{\n    using var buffer = new MemoryStream();\n    await sourceStream.CopyToAsync(buffer); buffer.Position = 0;\n    await container.SaveAsync(name, buffer);\n}","preventionTips":["Buffer non-seekable/network streams into a MemoryStream before saving.","Prefer seekable streams so Length is deterministic.","Be aware the AWS provider wraps your stream in LeaveOpenStreamWrapper internally."],"tags":["aws","stream","blob-storage","upload","abp"],"backgroundTag":null,"analyzedSha":"7ed43b1931b9df46a50c0c59148a18645641d0df","analyzedAt":"2026-08-13T16:26:11.351Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}