angular/angular
Debugging
Strategies for debugging both Angular itself and the framework's tests. The full canonical reference is contributing-docs/debugging-tips.md; this page is a quick, contributor-oriented index.
Focusing tests
Use Jasmine's focus modifiers to run only the test you're investigating:
fdescribe('Router', () => {
fit('should restore scroll position on navigation', async () => {
debugger; // Pause the debugger here.
// ...
});
});Pair fit/fdescribe with a debugger; statement. Run the test with Bazel's debug config (look up the exact flag for the target's runner — --config=debug for many nodejs_test targets, --karma_debug for ng_web_test_suite).
The ng.* browser console tools
When a development build of an Angular app is loaded, the framework attaches debug helpers under the global ng object. They are defined in packages/core/src/render3/global_utils_api.ts and registered via setGlobalUtils:
| Helper | What it does |
|---|---|
ng.getComponent(el) |
Returns the component instance backing a DOM element. |
ng.getDirectives(el) |
Returns directive instances on an element. |
ng.getOwningComponent(el) |
Returns the parent component context. |
ng.getInjector(el) |
Returns the element injector. |
ng.applyChanges(component) |
Marks the component dirty and triggers a tick. |
ng.profiler.timeChangeDetection() |
Times change-detection cycles repeatedly. |
ng.profiler.timeChangeDetection({record: true}) |
Records a CPU profile while measuring. |
ng.profiler.timeChangeDetection({record: true}) is the canonical way to investigate jank. The recorded profile shows up in the Chrome Performance tab as "Change Detection".
Angular DevTools
The browser extension at devtools/ is the GUI debugger. It exposes a component tree, the injector graph, and a profiler that records change-detection cycles with per-component timings. Build a debug version locally with pnpm devtools:build:chrome:debug and load it into Chrome Developer Mode (see apps/devtools).
DevTools talks to the inspected page via message passing:
graph LR Page["Inspected page<br/>(running app)"] --> CS["content_script_bundle.js<br/>(content script)"] CS --> Backend["backend_bundle.js<br/>(injected script)"] Backend --> Page CS --> Panel["DevTools panel UI<br/>(in iframe)"] Panel --> CS
Each script file lives under devtools/projects/. When something is wrong with a DevTools change, identifying which script side is at fault — content script vs panel UI vs backend — is the most useful first step.
Source-mapped builds
Bazel --compilation_mode=dbg (or, for esbuild-driven targets, sourcemap = "inline" in tools/defaults.bzl) preserves source maps in built bundles. Without source maps, stack traces from dist/ reference minified line numbers.
For a development DevTools build, the devtools:build:chrome:debug script already passes the right flags.
Common stuck points
"My change isn't being picked up"
- Disable the Angular CLI disk cache (
ng cache disable) when testing locally built packages against an external app. - Pass
--preserve-symlinks --preserve-symlinks-mainto Node when running the CLI to avoid symlink resolution turning@angular/coreinto a different copy than the one you built.
"The test passes locally but fails on CI"
- Run
pnpm bazel clean --expungeand retry. Stale Bazel state is the most common cause. - Confirm your test isn't depending on a specific machine timezone or locale; use
useAutoTick()and explicit locale providers.
"Tests using fixture.detectChanges() pass but the change appears wrong"
The codebase is migrating to zoneless. detectChanges() masks ordering bugs that the production code path exposes. Convert the test to use await fixture.whenStable() per testing.
"Hydration mismatch in SSR"
platform-server produces hydration annotations that the client matches at boot. A mismatch logs a warning at runtime. Steps:
- Find the offending component in the warning message.
- If it manipulates DOM directly, mark it
ngSkipHydration. - Otherwise, look at
packages/core/src/hydrationfor the matching annotation type and verify the client-side template structure equals the server's.
The integration/platform-server-hydration test is the canonical reproduction harness when fixing hydration bugs.
Debugging the compiler
The most useful entry point when debugging ngtsc:
- Set a breakpoint in
packages/compiler-cli/src/main.tsat the top ofmain(). - Run
node --inspect-brk node_modules/@angular/compiler-cli/bundles/main.js -p tsconfig.app.jsonagainst a small reproduction project. - Step into
performCompilation()then intongtsc/program.ts:NgtscProgram.
Annotation handlers live under ngtsc/annotations/. Each handler implements analyze, resolve, and compile methods; the failure usually shows up in one specific phase.
Logging
The framework defers to plain console.log for runtime warnings. The console.ts shim in packages/core/src/console.ts abstracts console for SSR (so warnings don't double-print). When adding a new warning:
- Use
formatRuntimeError()frompackages/core/src/errors.ts. - Assign a numeric error code per the existing range. The code is what links the runtime warning to the documentation page on angular.dev.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.