{"record":{"id":"415835971a7fcce6","repo":"stride3d/stride","slug":"invalid-state-for-resource-commandlistfencevalue","errorCode":null,"errorMessage":"Invalid state for {resource.CommandListFenceValue}","messagePattern":"Invalid state for (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Graphics/Direct3D12/CommandList.Direct3D12.cs","lineNumber":2289,"sourceCode":"                    // used in command list which hasn't be submitted yet? (only valid if our own, checked later)\n                    resource.UpdatingCommandList is not null\n                    // updated in a previous command list which hasn't be finished yet\n                    || (resource.CommandListFenceValue is not null && !GraphicsDevice.CommandListFence.IsFenceCompleteInternal(resource.CommandListFenceValue.Value)))\n                {\n                    if (doNotWait)\n                    {\n                        return new MappedResource(resource, subResourceIndex, dataBox: default);\n                    }\n\n                    if (resource.UpdatingCommandList == this)\n                        // Need to flush? (check if part of current Command List)\n                        // resource.CommandListFenceValue should be set after\n                        FlushInternal(wait: false);\n                    else if (resource.UpdatingCommandList is not null)\n                        throw new InvalidOperationException(\"CommandList updating the staging resource has not been submitted\");\n\n                    if (resource.CommandListFenceValue is null)\n                        throw new InvalidOperationException($\"Invalid state for {resource.CommandListFenceValue}\");\n\n                    GraphicsDevice.CommandListFence.WaitForFenceCPUInternal(resource.CommandListFenceValue.Value);\n\n                    // We're now up to date, remove command list fence value (if any)\n                    resource.CommandListFenceValue = null;\n                }\n            }\n\n            // Also make sure all copy queues are done\n            // (important for all cases, since it uploads initial data and also set resource barrier)\n            if (resource.CopyFenceValue.HasValue)\n            {\n                GraphicsDevice.CopyFence.WaitForFenceCPUInternal(resource.CopyFenceValue.Value);\n                resource.CopyFenceValue = null;\n            }\n\n            scoped ref var fullRange = ref NullRef<D3D12Range>();\n","sourceCodeStart":2271,"sourceCodeEnd":2307,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Graphics/Direct3D12/CommandList.Direct3D12.cs#L2271-L2307","documentation":"After confirming no other unsubmitted command list owns the staging resource, Map expects a recorded CommandListFenceValue to wait on. If it is null, internal state is inconsistent (no fence value was recorded for the last submission), so the code throws InvalidOperationException with the interpolated value.","triggerScenarios":"Mapping a staging resource whose last updating command list was submitted but for which CommandListFenceValue was never set — typically after misuse of low-level flush APIs, resetting fences manually, or skipping the normal Update path that records the fence value.","commonSituations":"Custom render-loop code that submits command lists directly without going through the resource-tracking helpers; resource reused across device resets/recreation where fence bookkeeping was cleared; engine-level bugs.","solutions":["Ensure the staging resource was last written via CommandList.Update on a properly submitted command list so the fence value is recorded.","Don't manually clear/reset resource.CommandListFenceValue or device fences in application code.","Recreate the staging resource if its tracking state is suspected corrupt.","If reproducible with straightforward API usage, report as an engine bug (this is an internal invariant)."],"exampleFix":"// before\nresource.CommandListFenceValue = null; // manual clearing corrupts state\ncommandList.Map(resource, MapMode.Read, 0); // throws\n// after\n// let the engine manage fence values; update then map:\ncommandList.Update(resource, data);\ncommandList.Flush();\ncommandList.Map(resource, MapMode.Read, 0);","handlingStrategy":"try-catch","validationCode":"if (resource.CommandListFenceValue is null && resource.UpdatingCommandList is null)\n{\n    // no tracked submission: refresh state by recreating or re-uploading the resource\n}","typeGuard":null,"tryCatchPattern":"try { commandList.Map(stagingResource, MapMode.Read, 0); }\ncatch (InvalidOperationException ex) when (ex.Message.StartsWith(\"Invalid state\"))\n{ /* fence bookkeeping corrupt: recreate resource or re-run Update path */ }","preventionTips":["Always write staging resources through CommandList.Update so fence values are tracked.","Never manually mutate CommandListFenceValue or device fences from app code.","Treat this as an engine invariant violation: report reproducible cases upstream."],"tags":["direct3d12","graphics","fence","invariant"],"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-23T08:17:48.524Z"}