Support tickets describe symptoms, not causes. This table maps what people report to the cause we reproduced on staging and the fix. Every row was observed with the demo service or confirmed in the engine code.
Symptom → cause → fix
| Symptom | Cause | Fix | Lesson |
|---|---|---|---|
Applicant cannot submit: 403 UNAUTHORIZED_ROLE_ON_TRANSITION |
APPLY is not authorised for the applicant's role (the demo broke it with ROLE_AGENT only) | Authorise the applicant roles on NEW → APPLY | D6 drill A |
| Paid, "Submitted for Processing", no officer ever sees it | OFFICE_ASSIGNMENT failed (OFFICE_NOT_FOUND, no office at that location) or the office has no active officer |
Fix the office, then re-trigger ASSIGN_OFFICE (support) | D6 drill B |
| Approve button missing for an officer | The officer is not in the transition's authorisedRoles / authorisedUsers | Authorise the right role; avoid authorisedUsers | D6 drill C1 |
| Empty red toast, 500 on process-application | The transition's end state code does not exist (typo). The portal saved it without checking | Fix the state code; the officer retries | D6 drill C2 |
Submit fails: INVALID_DYNAMIC_PRICE_CONFIGURATION_WITHOUT_PRICE_VALUE |
No pricing scenario matched | Cover every combination; order scenarios | B1, B2 |
Submit fails: INVALID_FORMULA |
The pricing formula cannot be evaluated | Fix the formula; search "Invalid formula" in Kibana | B4 |
| Paid service creates no bill | No BILL_ID_GENERATION action on APPLY | Add the breaking bill action | B6 |
APPROVE fails with CERTIFICATE_GENERATION_ACTION_ERROR |
certificateExpirationDays missing, or wrong template code | Set the days (0 = never expires) and the template code per language | B9 |
| Certificate shows empty district / sector | Dotted key read as ${(X.label)} |
Use ${.vars["X.label"]!""} |
B9 |
| Next steps never shown | The Condition field contains free text; it must be JavaScript (empty = always) | Clear it or write model => model.price > 0 |
D3 |
Save returns INVALID_CHANGE_REQUEST_STATUS |
The change request is not In Development (In QA, Ready To Go Live, Live) | Wait, ask for it to be sent back, or start a Service Improvement | A1, D3 |
| Link bounces to /dashboard/stats | Wrong institution in the organization portal | Switch the institution first | A2, D2 |
| External call never happens | URL_CALL is not implemented | Use INTEGRATION with an endpoint code | B7 |
| Application stuck after a failed system event | System events retry 3 times, 60 s apart, then stop | Fix the cause, ask support to re-trigger the event | D6 |
| Valid-until date before the event it covers | certificateExpirationDays too short (demo: 7 days for a trip 15 days later) | Choose days that fit the use case | B9 |
Synchronous vs asynchronous failures
| User action (APPLY, APPROVE, REJECT…) | System event (ASSIGN_OFFICE, PAY, nextEvent…) | |
|---|---|---|
| How it runs | Synchronous HTTP call, one traceId per click | Message on the queue (Pulsar), a new traceId per attempt |
| What the user sees | An error toast (sometimes empty) or a 4xx/5xx in DevTools | Nothing: the application looks normal but does not move |
| Retries | The user clicks again after the fix | 3 retries, 60 s apart, then it stops |
| After the fix | Works on the next click | Support re-triggers the event (retry endpoint); the engine logs PROCESSING_FAILURE_RESOLVED |
| Kibana | PROCESSING_FAILURE_TRACKER with source=PROCESSING_ENDPOINT |
PROCESSING_FAILURE_TRACKER with source=INTERNAL |
Gotcha · the portal does not validate your workflow
The Service Management Portal accepted a workflow whose end state does not exist and one whose office does not exist. Nothing complained until an application reached that transition. Test every transition before you submit to QA.
An applicant paid two days ago and the status still says "Submitted for Processing". The officer inbox is empty. What do you check first?
B. Paid + no officer = the office assignment (a system event) failed after its retries. The tracker line names the event and the error.
← D3 · Change a live service: Service Improvement · D5 · Kibana: find an application's story →