feat(errors): classify the install 'no store entry' failure
Some checks are pending
Security / Security check (push) Waiting to run

Even with the honest install badge the hub error stays reachable
(stale store snapshot, race with a store refresh, older hub). The
friendly-error mapper now gives it its own headline plus a hint
naming the three acquisition paths — local module install, adding
the providing store, configuring the MCP/n8n integration — in EN
and DE, with the verbatim hub message kept copyable. Matcher unit
tests EN+DE guard the classification.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-07-22 13:48:31 +02:00
parent 08227410e6
commit e28fffee61
7 changed files with 87 additions and 2 deletions

View file

@ -40,12 +40,12 @@ void main() {
final l = await _loadL10n(const Locale('en'));
final r = friendlyError(
_FakeGrpcError(9, 'FAILED_PRECONDITION',
'install error: no store entry for system.approval'),
'install error: module manifest is invalid'),
l,
);
expect(r.headline, l.errFailedPrecondition);
expect(r.hint, l.errFailedPreconditionHint);
expect(r.detail, contains('system.approval'));
expect(r.detail, contains('manifest'));
});
test('NOT_FOUND has a recovery hint', () async {
@ -151,5 +151,45 @@ void main() {
);
expect(r.headline, l.errMissingValue);
});
test('no-store-entry maps to the three-path recovery hint', () async {
// The flow quick-fix dead end: even with the honest badge this
// error stays reachable (stale store snapshot, refresh race,
// older hub) it must never render as the generic
// FAILED_PRECONDITION copy again.
final l = await _loadL10n(const Locale('en'));
final r = friendlyError(
_FakeGrpcError(
9,
'FAILED_PRECONDITION',
"install error: no store entry for 'example-provider/tool.summarize'"
' — run `chain store search <term>` to see what\'s available',
),
l,
);
expect(r.headline, l.errNoStoreEntry);
expect(r.hint, l.errNoStoreEntryHint);
// The hint names all three acquisition paths.
expect(r.hint, contains('chain install --link'));
expect(r.hint, contains('Stores'));
expect(r.hint, contains('integration'));
// The verbatim hub message stays copyable.
expect(r.detail, contains("example-provider/tool.summarize"));
});
test('no-store-entry is classified in German too', () async {
final l = await _loadL10n(const Locale('de'));
final r = friendlyError(
_FakeGrpcError(
9,
'FAILED_PRECONDITION',
"no store entry for 'x.y' — run `chain store search <term>`",
),
l,
);
expect(r.headline, l.errNoStoreEntry);
expect(r.hint, contains('chain install --link'));
expect(r.hint, contains('Anbindung'));
});
}