stride3d/stride · error · InvalidOperationException
The character ' ' upload has been requested while its…
Error message
The character '{character.Character}' upload has been requested while its current glyph is valid. What it means
The font atlas cache refuses to upload a glyph whose bitmap was already uploaded for the current valid glyph state. If CharacterSpecification.IsBitmapUploaded is true, re-requesting an upload indicates duplicate cache management, so it throws InvalidOperationException naming the character.
Solutions
- Check character.IsBitmapUploaded before calling UploadCharacterBitmap and skip if true
- Ensure only one code path owns uploading characters per frame
- If the glyph must be re-uploaded, invalidate the character's glyph state first so IsBitmapUploaded resets
- Investigate unexpected cache clear/invalidation logic that leaves IsBitmapUploaded inconsistent
Example fix
// before
cacheManager.UploadCharacterBitmap(commandList, character);
// after
if (!character.IsBitmapUploaded)
cacheManager.UploadCharacterBitmap(commandList, character); Defensive patterns
Strategy: validation
Validate before calling
if (character.IsBitmapUploaded) return; // already in atlas
Type guard
bool NeedsUpload(CharacterSpecification c) => c.Bitmap != null && !c.IsBitmapUploaded;
Try / catch
try { cache.UploadCharacterBitmap(commandList, character); }
catch (InvalidOperationException ex) when (ex.Message.Contains("upload has been requested"))
{
// glyph already valid in atlas; safe to ignore
} Prevention
- Single choke point for glyph uploads to prevent duplicates
- Check IsBitmapUploaded before every upload call
- Ensure cache clears also reset per-character upload state
When it happens
Trigger: Calling UploadCharacterBitmap twice for the same character while its glyph is still valid (not evicted and not invalidated).
Common situations: Double-enqueueing characters during the same frame (e.g. drawing the same text twice through separate code paths that both force uploads); cache invalidation logic that fails to reset IsBitmapUploaded or clears without resetting state.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- character
- The rendered character is too big for the cache texture
- Could not find asset
- Expect name1=value1;name2=value2 format.
- assetItem must be an absolute path
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/a05664cf31559a35.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/Font/FontCacheManager.cs:70
{
foreach (var character in cachedCharacters)
character.IsBitmapUploaded = false;
cachedCharacters.Clear();
packer.Clear(cacheTextures[0].ViewWidth, cacheTextures[0].ViewHeight);
}
/// <summary>
/// Upload a character's bitmap into the current cache.
/// </summary>
/// <param name="character">The character specifications corresponding to the bitmap</param>
public void UploadCharacterBitmap(CommandList commandList, CharacterSpecification character)
{
if (character.Bitmap == null)
throw new ArgumentNullException("character");
if (character.IsBitmapUploaded)
throw new InvalidOperationException($"The character '{character.Character}' upload has been requested while its current glyph is valid.");
var targetSize = new Int2(character.Bitmap.Width, character.Bitmap.Rows);
if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))
{
// not enough space to place the new character -> remove less used characters and try again
RemoveLessUsedCharacters();
if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))
{
// memory is too fragmented in order to place the new character -> clear all the characters and restart.
// TODO: This is invalid, we might delete character from current frame!
ClearCache();
if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))
throw new InvalidOperationException("The rendered character is too big for the cache texture");
}
}
// Upload the bitmap to the atlas texture, with a 1px transparent border extending
// beyond the allocated region to clear any stale pixels from previously freed glyphs.
// This overlaps into neighbors' transparent borders (which are also zeroed), so noView on GitHub (pinned to 96fad776d2)