File-New-Project/EarTrumpet · error · NotImplementedException

Missing resource: {res}

Error message

Missing resource: {res}

What it means

PartViewModel is the base class for every trigger/condition/action view model in the EarTrumpet.Actions addon. Its AddText and LinkText properties both call ResolveResource(suffix), forming the key "{Part.GetType().Name}_{suffix}" against the Actions resx. Because every concrete Part-derived data type flows through this base, each one must ship both "{TypeName}_AddText" and "{TypeName}_LinkText" resource strings. A null/whitespace lookup throws NotImplementedException, which is a hard failure during UI binding.

Source

Thrown at EarTrumpet/Addons/EarTrumpet.Actions/ViewModel/PartViewModel.cs:75

            Part = part;
        }

        protected void Attach(INotifyPropertyChanged obj)
        {
            obj.PropertyChanged += (s, e) =>
            {
                RaisePropertyChanged(e.PropertyName);
                RaisePropertyChanged(nameof(LinkText));
            };
        }

        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

  1. For the offending Part type name (shown in the thrown message), add both "{TypeName}_AddText" and "{TypeName}_LinkText" to Resources.resx and each localized resx.
  2. Audit all Part-derived types (search for ': Part' / ': BaseTrigger' / ': BaseCondition' / ': BaseAction') and ensure each has AddText + LinkText resx entries.
  3. If you renamed the type, update the resx key prefix to match the new GetType().Name.
  4. Add a unit test that reflects over all Part subtypes and asserts both keys resolve non-empty.

Example fix

// before: new action type has no resx strings
//   public class SetDefaultDeviceAction : BaseAction { }

// after: add resx entries
//   <data name="SetDefaultDeviceAction_AddText"><value>Set as default</value></data>
//   <data name="SetDefaultDeviceAction_LinkText"><value>device</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

When it happens

Trigger: Any XAML binding or code access to AddText / LinkText on a PartViewModel whose wrapped Part runtime type lacks one of the resx keys. E.g. a new action type 'SetDefaultDeviceAction' is rendered before "{SetDefaultDeviceAction}_LinkText" exists.

Common situations: Adding a new Part subclass (new action/condition/trigger) without adding its two resx entries; renaming a Part type without mirroring the resx; partial localized resx missing the keys for some parts.

Related errors


AI-assisted analysis of File-New-Project/EarTrumpet@aa894e51c2 (2026-08-13). Data as JSON: /api/errors/647f209f5da82245. Report an issue: GitHub.