File-New-Project/EarTrumpet · error · NotImplementedException
Missing resource: {res}
Error message
Missing resource: {res} What it means
TextViewModel wraps an IPartWithText and exposes PromptText (always) and EmptyText (from ToString when the part's Text is blank). ResolveResource builds "{_part.GetType().Name}_{suffix}", so the CONCRETE runtime type behind the IPartWithText interface must supply "{ConcreteType}_PromptText" and "{ConcreteType}_EmptyText" resx strings. Missing either throws NotImplementedException.
Source
Thrown at EarTrumpet/Addons/EarTrumpet.Actions/ViewModel/TextViewModel.cs:45
public override string ToString()
{
if (string.IsNullOrWhiteSpace(_part.Text))
{
return ResolveResource("EmptyText");
}
else
{
return _part.Text;
}
}
private string ResolveResource(string suffix)
{
var res = $"{_part.GetType().Name}_{suffix}";
var ret = Properties.Resources.ResourceManager.GetString(res);
if (string.IsNullOrWhiteSpace(ret))
{
throw new NotImplementedException($"Missing resource: {res}");
}
return ret;
}
}
}
View on GitHub (pinned to aa894e51c2)
Solutions
- Identify the concrete _part type name (from the thrown message) and add "{TypeName}_PromptText" and "{TypeName}_EmptyText" to Resources.resx and localized resx files.
- Enumerate all IPartWithText implementations and confirm each has both keys.
- Match the resx key prefix to the exact GetType().Name after any rename.
- Rebuild so the resx is recompiled into the assembly.
Example fix
// before: IPartWithText impl 'PromptTextPart' has no strings // after resx: // <data name="PromptTextPart_PromptText"><value>Enter text</value></data> // <data name="PromptTextPart_EmptyText"><value>(empty)</value></data>
Defensive patterns
Strategy: validation
Validate before calling
var key = $"{_part.GetType().Name}_{suffix}";
var value = Properties.Resources.ResourceManager.GetString(key);
if (string.IsNullOrWhiteSpace(value)) { Trace.WriteLine($"Missing resource: {key}"); return string.Empty; } Try / catch
try { return ResolveResource(suffix); } catch (NotImplementedException ex) { Trace.WriteLine(ex); return string.Empty; } Prevention
- Because IPartWithText hides the concrete type, enumerate every implementer in a test and assert its PromptText/EmptyText keys.
- Add resx entries whenever a new IPartWithText implementation is introduced.
- Keep resx key prefixes aligned with GetType().Name after renames.
When it happens
Trigger: The UI binds PromptText (always evaluated) or calls ToString() when _part.Text is empty, and the concrete part type name lacks the corresponding resx key. The interface IPartWithText hides the real type, so the failure surfaces only at runtime for whichever implementation is active.
Common situations: A new IPartWithText implementer was added without PromptText/EmptyText resx entries; the implementing class was renamed; a localized resx omits the keys.
Related errors
AI-assisted analysis of File-New-Project/EarTrumpet@aa894e51c2 (2026-08-13).
Data as JSON: /api/errors/55bad2abdd17d5e4.
Report an issue: GitHub.