stride3d/stride · error · ArgumentException
Invalid delta on reference count. It must be non-negative…
Error message
Invalid delta on reference count. It must be non-negative after updating. Current reference count: [{resourceLink.ReferenceCount}] Delta: [{referenceDelta}] What it means
UpdateCounter validates that applying referenceDelta to the resource link's current ReferenceCount never yields a negative count; if it would, ArgumentException is thrown with the current count and delta in the message. This guards against unbalanced ReleaseReference calls or corrupt bookkeeping in GetTemporaryResource/UpdateReferenceCount.
Solutions
- Balance every AddReference with exactly one ReleaseReference; audit call sites for extra releases.
- Do not release a resource whose reference count is already zero; track ownership explicitly.
- Use GetTemporaryResource/its disposal pattern instead of manual add/release to avoid miscounting.
- Serialize access (locking) if the allocator is shared across threads.
Example fix
// before
allocator.ReleaseReference(texture); // called twice by mistake
allocator.ReleaseReference(texture);
// after
using (var temp = allocator.GetTemporaryResource(texture))
{
// use resource; released exactly once on dispose
} Defensive patterns
Strategy: validation
Validate before calling
if (referenceCount + delta < 0)
throw new InvalidOperationException("Unbalanced release detected"); Type guard
bool CanRelease(GraphicsResourceLink l, int delta) => l.ReferenceCount + delta >= 0;
Try / catch
try { allocator.ReleaseReference(texture); }
catch (ArgumentException ex) { log.Error("refcount underflow", ex); } Prevention
- Pair every AddReference with exactly one ReleaseReference
- Prefer GetTemporaryResource with using/dispose
- Guard shared allocators with locks
When it happens
Trigger: Releasing a resource more times than it was referenced (delta such that ReferenceCount + delta < 0), e.g. double ReleaseReference, or calling ReleaseReference on a temporary resource whose count already reached 0.
Common situations: Asymmetric Add/Release calls across code paths or exception handlers; reusing a stale resource handle after recycling reset its count; concurrency bugs where two threads release the same resource.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Binding describes an array larger than dataOuter
- Binding describes an array larger than dataOuter
- Cannot generate more than 65535 indices on feature level HW…
- Control points apply only to PrimitiveType.PatchList
- destination length does not match the amount of indices…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/38e77c3489072bd3.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/GraphicsResourceAllocator.cs:544
// Resource not found in the cache
return false;
}
/// <summary>
/// Updates the reference count for a specified Graphics Resource.
/// </summary>
/// <param name="resourceLink">The Graphics Resource whose reference count is to be updated.</param>
/// <param name="referenceDelta">
/// The change in the reference count. Positive values increase the count, while negative values decrease it.
/// </param>
/// <exception cref="ArgumentException">
/// The <paramref name="referenceDelta"/> is invalid. It cannot make the reference count of the <paramref name="resource"/> negative.
/// </exception>
private void UpdateCounter(GraphicsResourceLink resourceLink, int referenceDelta)
{
if ((resourceLink.ReferenceCount + referenceDelta) < 0)
{
throw new ArgumentException("Invalid delta on reference count. It must be non-negative after updating. " +
$"Current reference count: [{resourceLink.ReferenceCount}] Delta: [{referenceDelta}]");
}
resourceLink.ReferenceCount += referenceDelta;
resourceLink.AccessTotalCount++;
resourceLink.AccessCountSinceLastRecycle++;
resourceLink.LastAccessTime = DateTime.Now;
// If no alive references are left, we can tag the resource for discarding on next Map
if (resourceLink.ReferenceCount == 0)
GraphicsDevice.TagResourceAsNotAlive(resourceLink);
}
}
}
View on GitHub (pinned to 96fad776d2)