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.

SCSS / sass errors

Fix. Check Node and npm versions first, then:

sudo npm rebuild node-sass

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.

python3: command not found during setenv.sh

Cause. generate_gci.py computes the workflow GCI for non-release environments.

Fix. Install Python 3. Only ENV_NAME=release skips this step.

Husky hooks are not running

Cause. husky install runs in postinstall; it is skipped if npm install was run with --ignore-scripts.

Fix. npm run init:husky.

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. RouteAccessResolver decodes it on every guarded navigation and logs out when the token claim is in the past.

  • A request returned 401; AuthInterceptor dispatches Logout with "Auth token expired, please try to login again."

  • The user record has no loginId.

There is no token refresh. See authentication.

After login I land on the wrong page

Cause. sessionStorage['loginRedirectUrl'] is set by RouteAccessResolver and never cleared after use, so a stale value can survive.

Fix. Clear sessionStorage for the origin.

The app does not work in incognito

Expected. Stated in the README. The app depends on localStorage, sessionStorage and a cross-subdomain cookie.

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.

Toggling a flag does not re-render a component

Expected. appEnabledByFeatureFlag evaluates once, in its input setter. Reload.

A menu item is missing but the URL works

Expected for flags applied only in the sidebar. FeatureFlagsGeneralGuard always passes; only FeatureFlagGuard (used on two routes) redirects to /404.

Permissions

A user cannot reach a page they should be able to

Check, in order.

  1. Does the user hold REST_UW_ACCESS or ADVANCE_AUDITORS? Those are deny filters applied across nearly every route and menu item.

  2. Does the route use an allow clause? Only /admin (only: DEV) and underwriting/background-reports (only: FINANCE) do — and an allow-list blocks even super users without that exact code.

  3. Is the grant supplier-scoped? ngx-permissions discards the supplierKey scope, so route and template gating are scope-blind while the backend is not.

"Access denied." toast then redirect to /

Cause. SubPermissionsGuard — the route requires one of data.requireOneOfSubPermissions and the user has none. It also denies when the route data is missing or empty.

A REST_UW_ACCESS user sees a stripped-down UI

Expected. AppComponent adds a restricted-access class to document.body, which SCSS uses to hide UI wholesale, and the supplier aggregate load skips several calls for ADVANCE_AUDITORS.

EVA and iframes

An embedded region is blank

Check.

  1. The auth token: cookie PYBEvaToken on environment.domain when deployed, or ?auth=<jwt> in the iframe URL on localhost.

  2. The console for [IA] Sending / [IA] Received — no Received lines means messages are being dropped by the iframe-id or origin checks.

  3. 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.

An iframe stops resizing

Cause. ResizeIframeService.getElement throws 'Element not found!' when the target frame is gone, and the throw terminates the incomingMessage$ subscription — so all subsequent resize handling stops.

Fix. Reload.

document.domain errors in the console

Expected. CommunicationService.setDomain() assigns document.domain before every send, wrapped in an empty catch. The API is deprecated in modern browsers.

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.

A callback fires repeatedly / grows over time

Cause. B2bWorkflowService.subscribeTask creates a new inner subscription per received message and never tears them down.

Fix. Subscribe to taskMonitoring() directly and filter yourself.

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.

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.

A deployed build regressed something the tests cover

Cause. npm run test:ci is commented out of buildspec.yml. Only buildspec-ci.yml runs the unit suite, as a separate pipeline.

Cypress specs fail after a rename

Cause. cypress/support/commands.js imports from application source (AMAZON_SELLER_CENTRAL_MARKETPLACE_KEY, AMAZON_SELLER_CENTRAL). The suite is also marked unmaintained.

Console noise that is expected

Message Why

AG Grid enterprise licence warning

The key embedded in main.ts has an expired ExpiryDate. Functionality is unaffected.

[Feature Flags] Current Functionality Status: …

FeatureFlagsGeneralGuard prints the resolved table once per page load in non-production.

[IA] Sending … / [IA] Received …

CommunicationService logging the EVA protocol in non-production.

------- SILENT LOG DEBUG --------

The Logger helper, dev-only.

Elasticsearch is disabled. No events will be shown.

The event-rule editor’s example-events query is intentionally stubbed.

Please turn on the Payability VPN… every 30 seconds

VpnTesterService toasts on every failed probe while CHECK_VPN is on.

Duplicate .js hits when grepping

Committed build residue sits beside .ts sources. Exclude *.js from searches.

When nothing else works

  1. nvm use && rm -rf node_modules && npm install

  2. ./deployment/setenv.sh <env> "dev.payability.com" "$PWD/deployment"

  3. Clear localStorage, sessionStorage and cookies for the origin.

  4. npm run lint && npm run test-single to confirm the tree itself is sound.

  5. Check ./deployment/checkenv.sh — you may be pointed at a backend that is down.