Troubleshooting
Build and setup
TypeError: Cannot read property 'length' of undefined at createSourceFile
Cause. The environment file has not been generated.
Fix.
./deployment/setenv.sh exp "dev.payability.com" "$PWD/deployment"
This is the single most common first-run failure. See environments.
The …/src/environments/environment.prod.ts path in file replacements does not exist
Cause. Same root cause, hit from the production build path — angular.json’s
`production configuration replaces environment.ts with environment.prod.ts, which
set-env.ts writes only when ENV_NAME=release.
Fix. Run setenv.sh (with release if you genuinely want a production build).
Cannot read property 'config' of null on ng serve --open or npm test
Cause. Node/CLI version mismatch, usually after switching Node versions.
Fix.
nvm list
nvm use # picks up .nvmrc → 12.21.0
npm i
If that does not help, reinstall the CLI:
sudo npm uninstall -g @angular/cli
sudo npm install -g @angular/cli
The README documents a workaround for stubborn uninstalls: switch to an older Node
(nvm use v8.11.3), uninstall, switch back, reinstall.
The build runs out of memory
Cause. AOT compiling ~420 components exceeds Node’s default heap.
Fix. Use the high-memory scripts rather than plain ng build:
npm run build-prod # or build-test — both use --max_old_space_size=8192
CI uses 12288 (deployment/build.sh). See
build and deployment.
Runtime and login
Google sign-in silently does nothing
Cause. You are serving on a port that is not registered with the Google client.
Fix. Use one of 4200, 4300, 4400, 4500, 4600, 5000, 8082 — and remember 4600 is EVA’s dev port. See local development.
"Cannot connect with server" on login
Cause. Wrong backend, or the backend is down. LoginComponent maps other statuses
distinctly: 401 → "Invalid login or password", 403 → "Access denied".
Fix. Check which environment you configured (./deployment/checkenv.sh) and whether
that backend is up.
"Something change in google auth response"
Cause. The Google credential was absent from the callback payload —
AuthEffects.authLoginGoogle guards against Google changing its response shape.
Fix. Check for a Google Identity Services change and for third-party-cookie or tracking-prevention settings blocking the flow.
Logged out unexpectedly, or bounced to /login on navigation
Causes.
-
The JWT expired.
RouteAccessResolverdecodes it on every guarded navigation and logs out when thetokenclaim is in the past. -
A request returned
401;AuthInterceptordispatchesLogoutwith "Auth token expired, please try to login again." -
The user record has no
loginId.
There is no token refresh. See authentication.
Data looks stale
A supplier shows old values
Cause. supplier.suppliers[supplierKey] caches every supplier visited this session
and nothing invalidates it.
Fix. Trigger a refresh (FetchSupplierDetails({ supplierKey, refresh: true }) —
which also appends refreshTimestamp to bust any HTTP cache), or reload the page. See
suppliers.
A newly created user is missing from an assignee dropdown
Cause. UsersService.getPreparedCombinedList() caches users and groups in a
BehaviorSubject for the whole session, with no invalidation.
Fix. Reload. See caching and persistence.
The supplier list only shows a few suppliers
Expected. With no persisted query, the default is
created_since:<today − 1 day>. Change the query; it is persisted to
localStorage['suppliers_last_query'].
Reference data (states, countries) is wrong
Cause. The utils slice is cached in localStorage via lscache with a 24-hour
TTL.
Fix. Dispatch FetchUtilAttribute with refresh, or clear the
lscache-utilsState key.
A displayed ratio does not match the API response
Cause. On the balance-approval screen, a non-zero
short_to_long_mov_avg_ratio_rcv silently overwrites
short_to_long_mov_avg_ratio. See
balance approval.
Feature flags
A flag is on in the bundle but the feature is off
Cause. Global settings beat build flags — the resolved set is seeded from the
FEATURE_FLAGS_IA global setting, not from environment.featureFlags.
Fix. Enable it at /admin/feature-flags (needs DEV) and save to global settings,
or set a session override.
My session flag overrides disappeared
Cause. Someone saved to global settings, which stamps a newer lastChange than your
stored session timestamp — and session overrides older than the setting are discarded.
Fix. Re-apply them. See feature flags.
isEnabled() returns false when the flag should be on
Cause. isEnabled reads build flags plus sessionStorage only. It is correct
after FeatureFlagsGeneralGuard has run initFF() on a guarded navigation. Calling
it from a constructor that runs earlier (as AppComponent does for CHECK_VPN) can
read false on a cold load.
Fix. Move the check later in the lifecycle, or into a guard.
Permissions
A user cannot reach a page they should be able to
Check, in order.
-
Does the user hold
REST_UW_ACCESSorADVANCE_AUDITORS? Those are deny filters applied across nearly every route and menu item. -
Does the route use an allow clause? Only
/admin(only: DEV) andunderwriting/background-reports(only: FINANCE) do — and an allow-list blocks even super users without that exact code. -
Is the grant supplier-scoped?
ngx-permissionsdiscards thesupplierKeyscope, so route and template gating are scope-blind while the backend is not.
See authorisation.
EVA and iframes
An embedded region is blank
Check.
-
The auth token: cookie
PYBEvaTokenonenvironment.domainwhen deployed, or?auth=<jwt>in the iframe URL onlocalhost. -
The console for
[IA] Sending/[IA] Received— noReceivedlines means messages are being dropped by the iframe-id or origin checks. -
Whether EVA itself is up (
env.evaApiUrl).
It works locally but not deployed (or vice versa)
Cause. Local and deployed differ in where the token lives — query parameter versus
cookie — and origin checks always allow localhost on non-production builds.
Long-running jobs
Progress stops updating during a Load Earnings / Load Remittance
Cause. SseService propagates any onerror or JSON parse failure as an observable
error, which terminates the stream. There is no reconnect.
Fix. Reload to re-open the stream. See real-time streams.
Payments and processes
/processes/approval shows the wrong screen
Expected. :supKey is declared before approval in the /processes table, so the
URL matches PendingEditComponent.
Fix. Use /proceses/approval — one s. See
processes.
Two error toasts for one failure
Expected. PendingInterceptorService toasts any 5xx, and the calling service or
component toasts as well. PaymentBatchRepositoryService adds its own message per
operation. See error handling.
Provider filtering on the card list appears ignored
Cause. CardManagementService.getCards sends the provider filter as a body on a
GET request, which some proxies drop.
See card programmes.
Tests
Tests pass individually but fail together
Cause. Karma runs with jasmine.random: false and ng-bullet’s
`configureTestSuite shares the TestBed across a suite. A spec that writes to
localStorage/sessionStorage, or sets cerialize casing via
DeserializeKeysFrom/SerializeKeysTo, leaks into the next.
Fix. Clean up in afterEach. See testing.
Karma cannot find Chrome
Cause. karma.conf.js sets CHROME_BIN from Puppeteer’s bundled binary.
Fix. Reinstall so the Puppeteer download completes (npm install), or set
CHROME_BIN yourself.
Console noise that is expected
| Message | Why |
|---|---|
AG Grid enterprise licence warning |
The key embedded in |
|
|
|
|
|
The |
|
The event-rule editor’s example-events query is intentionally stubbed. |
|
|
Duplicate |
Committed build residue sits beside |
When nothing else works
-
nvm use && rm -rf node_modules && npm install -
./deployment/setenv.sh <env> "dev.payability.com" "$PWD/deployment" -
Clear
localStorage,sessionStorageand cookies for the origin. -
npm run lint && npm run test-singleto confirm the tree itself is sound. -
Check
./deployment/checkenv.sh— you may be pointed at a backend that is down.