Summary
RealUnitRegistrationService.completeRegistration decides whether a 400 is a content rejection (RegistrationRejectedException) or a generic ApiException by comparing error.message to the free-text string 'Invalid signature'. That mapping should use a stable API error code once the backend exposes one.
Evidence
lib/packages/service/dfx/real_unit_registration_service.dart:215 — error.message != 'Invalid signature'
test/packages/service/dfx/real_unit_registration_service_test.dart:315 — the test pins the same literal
lib/packages/service/dfx/exceptions/api_exception.dart:15-21 already classifies structured codes (KYC_LEVEL_REQUIRED, REGISTRATION_REQUIRED)
Found while reviewing #910. That PR is correct to stop mapping this 400 to "check your entries"; the string match is only a brittle contract, not a regression of the #905 fix.
Suggested follow-up
- Backend: return a stable code such as
INVALID_SIGNATURE on POST /v1/realunit/register/complete.
- App: classify on
error.code (or a dedicated ApiException subclass via fromJson).
- If a new exception type is added, enumerate it in
exception_surface_test.dart in the same PR.
Not a merge blocker for #910: if the message text ever changes, the UI falls back to the previous generic failure path rather than blocking registration.
Summary
RealUnitRegistrationService.completeRegistrationdecides whether a 400 is a content rejection (RegistrationRejectedException) or a genericApiExceptionby comparingerror.messageto the free-text string'Invalid signature'. That mapping should use a stable API error code once the backend exposes one.Evidence
lib/packages/service/dfx/real_unit_registration_service.dart:215—error.message != 'Invalid signature'test/packages/service/dfx/real_unit_registration_service_test.dart:315— the test pins the same literallib/packages/service/dfx/exceptions/api_exception.dart:15-21already classifies structured codes (KYC_LEVEL_REQUIRED,REGISTRATION_REQUIRED)Found while reviewing #910. That PR is correct to stop mapping this 400 to "check your entries"; the string match is only a brittle contract, not a regression of the #905 fix.
Suggested follow-up
INVALID_SIGNATUREonPOST /v1/realunit/register/complete.error.code(or a dedicatedApiExceptionsubclass viafromJson).exception_surface_test.dartin the same PR.Not a merge blocker for #910: if the message text ever changes, the UI falls back to the previous generic failure path rather than blocking registration.