SPFx Troubleshooting: Errors, Causes & Fixes
Diagnose SPFx failures layer by layer: Node.js, build, deployment, web parts, PnPjs, REST, Graph permissions, CORS, and production-only errors — with fixes.
- Published
- Reading time
- 24 min read
What you’ll learn
- Identify the failing layer
- Start with version information
- Node.js compatibility
- Multiple Node versions across projects
- npm install fails
On this page (72 sections)
Direct answer: SPFx failures are diagnosed layer by layer — symptom, likely cause, check, fix, verify — across environment, build, deployment, UI, data, identity, network, and production. This hub organizes every failure class that way so a developer arriving with an error finds the failing layer first instead of reinstalling everything.
Do not reinstall everything before identifying the failing layer. Random upgrades, lock-file deletion, and force flags turn one diagnosed problem into several undiagnosed ones. The universal flow below governs every section:
- Identify the exact symptom — the error text, not its paraphrase.
- Capture the exact error — console, terminal, network, or admin center.
- Identify where it fails — build, deploy, load, data, auth, or production.
- Verify versions and configuration — SPFx, Node, packages, environment.
- Check browser, network, and build logs — evidence before theories.
- Isolate the failing layer — one variable at a time.
- Apply the smallest corrective change — targeted, reversible.
- Retest — against the original symptom.
- Verify with the intended user and environment — personas, not just admins.
Jump to the failing area: Diagnostic matrix · Flowchart · Quick checklist · Node.js · Build · Deployment · Graph 403 · CORS · Dev vs production. Lifecycle depth: SPFx complete guide; navigation: SPFx hub.
Identify the failing layer
Every SPFx failure lives in exactly one layer first. Name it before touching anything: environment (Node, npm, toolchain), build (TypeScript, dependencies, bundling), package (solution packaging), deployment (App Catalog, site availability), UI (React, rendering), data (REST, PnPjs), identity (authentication), authorization (SharePoint and Graph permissions), network (CORS, APIs, throttling), or production (configuration, permissions, tenant differences). Layer-first diagnosis is the mental model for this entire page.
Start with version information
Version mismatch is a frequent source of SPFx build failures, so capture the full matrix before theorizing: SPFx version, Node.js version, npm version, key package versions, operating system where relevant, build toolchain generation, browser, and target tenant or environment. Safe, read-only starting commands:
node --version
npm --version
Record package versions from the lock file and manifest rather than memory. An accurate version snapshot turns most "suddenly broken" mysteries into visible changes — which the source-control section below exploits.
Node.js compatibility
Each SPFx release supports specific Node.js LTS versions — verified baseline: recent SPFx releases target Node.js v22 LTS, and SPFx runs only on LTS releases, never Current. Build failures after a Node upgrade, unsupported-engine errors, dependency installation failures, toolchain errors, and strange new runtime behavior all point here first:
- SPFx version — identified from the project.
- Supported Node version? — checked against current Microsoft documentation for that release.
- Yes — continue diagnosis elsewhere.
- No — switch to a compatible Node version; never force the toolchain onto an unsupported runtime.
Confirm compatibility per release before installing or upgrading anything — Node and SPFx move on independent schedules, and this guide states no universal version beyond the verified baseline above.
Official reference: Set up your SharePoint Framework development environment on Microsoft Learn.
Multiple Node versions across projects
Teams maintaining different SPFx generations legitimately need different Node versions side by side: Project A on one SPFx release with its compatible Node, Project B on another with its own. A Node version manager solves this by switching runtimes per project directory — discussed here as a concept, with no specific third-party tool prescribed. Never upgrade Node globally without checking every project the workstation builds.
npm install fails
Work the diagnostic order instead of reaching for deletion: Node version, npm version, package.json contents, lock-file state, then the first meaningful npm error — reading the first error, never the last screenful. Identify the dependency conflict and check package compatibility against the SPFx release. Deleting node_modules and the lock file is not the first solution: the lock file pins the reproducible dependency graph, and deleting it can introduce new versions that widen the failure.
Symptom: dependency resolution or engine compatibility error
Likely causes: unsupported Node runtime, React or Fluent UI mismatch, stale lock file, SPFx generation drift. Check: versions captured above against the release matrix, then the conflicting packages named in the first error. Fix: align the runtime or the declared range deliberately. Verify: clean install reproduces green from the lock file.
Peer dependency errors
Package A requires one major version while package B expects another — most often an unsupported React package, a Fluent UI mismatch, an old dependency, or SPFx version drift. Force and legacy-peer-deps flags are never a universal fix: they can suppress the symptom while leaving an unsupported graph that fails later at runtime. Understand the conflict, assess compatibility deliberately, and use overrides only with full knowledge of the consequences.
Cannot find module
- Cannot find module — the exact specifier recorded.
- Is the dependency declared? — in package.json, not just on disk.
- Installed? — present in node_modules at a compatible version.
- Correct import? — path, package name, and casing verified (imports are case-sensitive).
- Correct package version? — renames across majors caught here.
- Type package required? — missing declarations identified.
- Build again — only after the cause is addressed.
Missing dependencies, incorrect imports, renamed packages, version mismatch, casing, and missing types cover nearly every instance. Practical example: an import path that works on a case-insensitive workstation and fails everywhere else is a casing defect, not a tooling defect.
TypeScript errors
Type mismatches, missing properties, incorrect interfaces, unsupported language features, dependency type conflicts, and possibly incompatible TypeScript versions each get fixed at their layer. Never default to any as the fix — TypeScript errors usually reveal real contract problems between components, services, and APIs, and silencing them converts compile-time catches into production faults.
Symptom: type error after a dependency update
Likely causes: breaking type changes upstream, mismatched TypeScript version for the SPFx release. Check: the exact type expectation against the installed package version. Fix: adapt the consuming code to the real contract. Verify: clean build with no suppressions added.
React version problems
Hooks failing, packages expecting a different React major, type conflicts, and runtime rendering problems trace to version drift. Never independently upgrade React inside an SPFx project without verifying compatibility with the SPFx version — React support arrives per SPFx release line, and mismatched majors break hooks, types, and rendering together. Depth: SPFx and React.
Fluent UI dependency problems
SPFx version, React version, and Fluent UI package and version must stay mutually compatible. Never install the newest Fluent UI package blindly into an SPFx project — verify current guidance for the SPFx release first, because Fluent UI majors track React majors, and a mismatch breaks both types and runtime behavior at once.
Build fails
Read the first meaningful error — TypeScript, dependency, Node or toolchain, configuration, lint or test, packaging — because dozens of downstream errors typically cascade from one root cause. The first error names the layer; everything after it is debris. Classify before acting, and never start with destructive cleanup.
Symptom: long build log full of errors
Likely causes: single upstream failure cascading. Check: scroll to the first error, ignoring everything below it initially. Fix: address that error alone. Verify: rebuild and confirm the cascade collapses.
Build worked yesterday
Something changed: Node, npm, dependency graph, lock file, package versions, environment variables, branch, or configuration. Compare against source control — package.json, lock file, toolchain config, source, manifest, and packaging configuration diffs name the change directly. Never reset or discard developer changes automatically; the diff is evidence, and evidence gets read before anything is reverted.
Clean build
Cleaning generated artifacts helps only when stale outputs are the suspect — after toolchain changes, failed interrupted builds, or inexplicable staleness. Use the clean task provided by the current toolchain for the project's SPFx generation; legacy clean commands belong to legacy-toolchain projects and must never be published as universal current instructions. Clean to eliminate a suspect, never as a ritual before diagnosis.
Local development does not start
Development server failures, unavailable test environments, certificate problems, and builds that start but serve nothing each isolate differently. Verify current SPFx local-development behavior for the project's release — hosted workbench served locally is the current shape — and never reference obsolete workbench workflows as current. Check the server output first: port conflicts, certificate trust, and misconfiguration announce themselves there.
HTTPS development certificate
Where the current workflow still uses a local development certificate, browsers warn on untrusted issuers until the workstation trusts it. Trust once per workstation through the current toolchain command for the SPFx release, then re-verify trust state before deeper diagnosis when warnings persist. If a future toolchain changes this workflow, its current behavior replaces this section — always confirm against current setup guidance.
Solution builds but web part does not load
- Build successful — artifacts exist.
- Page loads? — isolate page versus component.
- Web part loads? — isolate loading versus data.
- Browser console — runtime exceptions named.
- Network — failed imports and calls listed.
- Manifest and configuration — identity and settings verified.
- Runtime dependency — versions actually loaded.
- Data and API call — permissions and endpoints tested.
Likely causes span runtime JavaScript errors, missing dependencies, incorrect configuration, API failures, and permission issues — the ordering above separates them with minimum wasted motion.
Web part not in toolbox
High-value symptom with a fixed diagnostic order: package deployed, solution available to the site, component type correct, manifest valid, feature and site deployment configuration correct, tenant-wide deployment behavior understood, page context supported. Verify current SPFx deployment behavior before giving exact steps — catalog models and deployment scopes evolve, while this ordering stays constant. Upload alone never proves availability; each gate needs its own confirmation.
Works in dev but not production
Compare the two environments across configuration, identity, permissions, data, deployment, and network: tenant and site URLs, list IDs, API endpoints, Graph permissions and approvals, user permissions, App Catalog state, configuration values, CORS posture, environment variables, and production data volume. Diff systematically instead of guessing — this flow deserves its thoroughness because environment drift causes the failures developers insist are impossible:
- Dev works — baseline behavior recorded.
- Compare configuration — every environment value diffed.
- Compare identity and permissions — developer versus real personas.
- Compare data — volume, shape, and access.
- Compare deployment — catalog, version, scope, approval.
- Compare network — CORS, endpoints, throttling.
Package creation fails
Cover the current package process for the project's toolchain generation: prerequisite build success, solution configuration validity, manifest correctness, package metadata, and toolchain match. Use current package commands only after verification against the release in use — legacy packaging commands belong to legacy-toolchain projects and are labeled as such wherever they appear.
Solution package not generated
Confirm the expected output location for the current toolchain, the prerequisite build and package steps that must precede it, and the tooling actually installed. Never assume legacy folder structures when the current toolchain stages artifacts differently — check the project's own configuration for where outputs land.
App Catalog upload problem
Wrong catalog, invalid package, conflicting existing version, tenant versus site-collection catalog confusion, insufficient rights, and package incompatibility each present differently. Understand tenant App Catalog versus Site Collection App Catalog scoping where current and relevant — broad distribution versus isolated availability is a governance decision with deployment consequences, confirmed against current Microsoft guidance.
Package uploaded but solution not available
- Package uploaded — present in the catalog.
- Deployment status? — deployed, not merely stored.
- Tenant-wide or site deployment? — scope matches intent.
- Site has the solution? — added where designed.
- Component available? — visible in supported surfaces.
- API permissions? — requested and approved.
- Browser and runtime errors? — clean console confirmed.
Upload never equals usable solution — each stage above is a separate gate with separate evidence.
New version not appearing
Package version not bumped, old package still deployed, browser or CDN caching, incomplete deployment, wrong catalog, or wrong environment. Verify deployment and version state before blaming caches — cache clearing without version evidence just hides the real staleness source, and the catalog always knows which version it serves.
SPFx manifest problems
Component IDs, aliases, supported hosts, properties, and version or configuration mismatches each break different stages — identity collisions break deployment, host mismatches hide components from surfaces, property mismatches break configuration. Use current manifest schema terminology, and never change GUIDs randomly to "fix" deployment: regenerated identities orphan upgrades and mask the real misconfiguration.
SharePoint REST 401 and 403
- REST request fails — status captured exactly.
- 401 or 403? — authentication versus authorization paths diverge here.
- Correct site? — context verified against the call.
- Current user access? — tested as that user.
- Correct endpoint? — paths and methods verified.
- Operation permission? — read versus write requirements.
- Request configuration? — headers and digest where writes apply.
- Retest — single variable changed.
A 403 most often means authorization or access problems, but multiple causes qualify — treat the status as the starting question, never the complete diagnosis. Depth: SPFx and PnPjs.
PnPjs request fails
Verify SPFI initialization against the current pattern, correct SPFx context, correct web and site, list existence, internal field names, user access, current PnPjs APIs, and query validity — in that order. Most PnPjs failures are initialization, naming, or access problems wearing API-shaped symptoms. Depth: SPFx and PnPjs, never duplicated here.
PnPjs 403
- PnPjs 403 — authorization failed.
- What resource? — exact list, library, or site named.
- Can the user access it manually? — browser test as that user.
- Read or write operation? — write requirements exceed read.
- Required SharePoint permission? — identified per operation.
- Correct site context? — initialization target verified.
- Graph or custom API involved? — separate approval chains checked.
- Retest — as the affected persona.
PnPjs never bypasses SharePoint permissions — a 403 is the platform working, and the fix is access or scope, not retry force.
PnPjs 404
Wrong site, wrong list, wrong title or ID, incorrect paths, missing files or folders, environment-specific configuration — check the actual target before changing code. Renames and environment drift cause most instances; the API is usually reporting accurately.
PnPjs returns no items
Check list and site context, filters, internal field names, permissions, query syntax, and whether data actually exists. An empty array is a valid answer to a valid query surprisingly often — never assume an API failure before verifying the question asked.
Lookup and person field query fails
Field internal name, field type, select and expand shape, property names, permissions, and current API syntax — in that order, with depth in the PnPjs guide. Lookups fail on naming and shape far more often than on platform behavior.
Microsoft Graph troubleshooting
Route by status first, then diagnose endpoint, permission, approval, user access, query, paging, and throttling. Depth throughout: SPFx and Microsoft Graph — summarized here, never duplicated:
Graph Request → Status?
├── 401 → Authentication / token / context
├── 403 → Permission / approval / access
├── 404 → Address / endpoint / context
├── 429 → Throttling / volume
└── Other → Query / paging / shape
Graph 401
Token and authentication issues, wrong resource or audience, expired or invalid context, custom API authentication confusion — never one universal cause. Isolate identity before touching scopes: sign-in and token acquisition first, audience second, custom API configuration third.
Graph 403
- Graph 403 — authorization failed, identity intact.
- Exact endpoint? — the precise call named.
- Required permission? — per current documentation.
- Permission requested? — declared in the package.
- Permission approved? — administrator decision recorded.
- Correct permission type? — delegated model verified.
- User has resource access? — effective access tested.
- Tenant policy? — conditional and governance rules.
- Retest — one variable at a time.
Graph permission requested but missing
Inspect the solution's declared API permission requirements in its current configuration syntax — never request broad scopes as a quick fix for a 403. Undeclared scopes fail regardless of admin willingness; the declaration is the prerequisite everything else builds on.
Graph permission pending approval
Requests wait in the administrative approval workflow until a tenant administrator decides. Verify current Microsoft guidance for where approvals surface rather than following outdated admin-center paths from old tutorials — and treat pending approval as a normal deployment state with an owner and a follow-up date, not as an error.
Permission approved but still 403
Approval proves one thing: the grant exists. Still verify the correct permission, endpoint, and permission type; the signed-in user's resource access; resource existence; tenant policy; token and context freshness where relevant; environment correctness; and any additional endpoint requirements. "Permission approved" never proves every Graph request should succeed — it proves exactly one link in a longer chain.
Graph Explorer works but SPFx fails
Different permission grants, application identities, user consent, and token contexts explain the gap. Explorer success validates the endpoint and query partially — it never proves SPFx permissions correct, which need separate verification of solution scopes, approval state, and real-user access.
Graph 404
Wrong IDs, wrong endpoints, deleted resources, incorrect tenant or resource context, unsupported routes — never treat every 404 as hidden permission failure. Verify addressing first; authorization theories wait their turn.
Graph 429
- 429 — throttled, not broken.
- Inspect retry guidance — server-provided where available.
- Reduce request pattern — select, page, batch, cache, debounce.
- Wait — honor the guidance.
- Retry appropriately — then keep volume down.
Use current Microsoft Graph Retry-After guidance with no invented delays. Throttling is a signal about request patterns, not an insult to work around with concurrency.
Graph paging bug
Only some users or items returned means one suspect: the next link. First page never equals complete dataset — follow provided continuation URLs on every collection, and link the Graph guide's paging patterns rather than re-deriving them here.
API permissions versus SharePoint permissions
SharePoint permissions decide what a user can do in SharePoint; Graph and API permissions decide what scopes are available to the application or context — and both may matter simultaneously. Never conflate them: a fully approved Graph grant changes nothing about SharePoint access, and site ownership changes nothing about Graph scopes.
Custom API authentication troubleshooting
Where the documented client mechanism for Entra-secured APIs applies and is verified as current for the release, diagnose 401s and 403s across wrong resource, unapproved permission, registration mismatch, and audience mismatch. Verify current APIs before publishing any deeper guidance — this section names the failure classes without prescribing unverified syntax.
External API 401
Authentication method, token audience, API registration, scopes or roles, tenant correctness, and backend authorization — checked without ever embedding credentials to "test faster." Temporary secrets in code become permanent secrets in history.
CORS error
The browser blocks cross-origin calls the API has not allowed — typically surfacing as blocked-by-CORS-policy failures. CORS is enforced by the browser from server response policy, and the correct fixes live server-side or in architecture: an allowed origin for sanctioned callers, or a secure backend and API layer where direct browser calls cannot be authorized. Never disable browser security, never use insecure public proxies, never embed credentials, and never attempt to set response headers from the SPFx request — Access-Control-Allow-Origin belongs to the API's responses, not to client code:
SUPPORTED: SPFx → Allowed Origin → API
SUPPORTED: SPFx → Secure Backend / API Layer → External Service
NEVER: Disable security · Public proxy · Embedded secrets
CORS versus authentication versus authorization
One failing request can involve all three layers: browser cross-origin policy first, then identity, then access. Diagnose in that order — CORS, authentication, authorization, resource — because fixing the wrong layer wastes the entire session:
- Browser — CORS policy satisfied?
- API — reached and responding?
- Authentication — identity established?
- Identity — correct principal and audience?
- Authorization — access granted to the resource?
- Resource — exists and behaves?
Client secret found in SPFx
Discovering a client secret, API key, password, or privileged credential in browser JavaScript triggers one response: move it server-side through secure architecture — never merely relocate it to another JavaScript file, environment file shipped to browsers, or obfuscated bundle. Browser code cannot securely hide confidential credentials, full stop. Treat the exposed credential as compromised and rotate it through proper channels.
React component not rendering
Check runtime console errors, props, state, conditional rendering, component imports, React compatibility, DOM and root setup, and async failures — in that order. Most non-rendering traces to thrown errors or never-satisfied conditions, not to framework mysteries. Depth: SPFx and React.
useEffect loop
Repeated API calls, degrading pages, and consequent Graph or PnPjs throttling point at effect dependencies: state updates inside effects re-triggering themselves, object or function dependencies recreated every render, missing cleanup. Never remove the dependency array blindly — that trades a loop for stale closures. Stabilize dependencies at their source (services constructed once, memoized callbacks where justified) and keep the array honest.
State updates after async requests
Unmounted components and superseded responses must never write state — guard with cancellation or ignore-stale-result patterns compatible with the API approach in use. Present only patterns verified for the current React and SPFx versions; outdated lifecycle warnings are not republished here as current behavior.
Web part is slow
Measure before optimizing: browser network tab first — how many requests, what payload sizes, any N+1 shape, large lists unpaged, Graph paging ignored, repeated effects refetching, bundle weight, render churn. Prioritize by evidence: data-access patterns dominate, rendering micro-optimization trails far behind.
Too many API requests
Effect loops, duplicated fetching across components, N+1 shapes, absent caching, uncontrolled parallel calls, and repeated initialization each multiply traffic. Fix the architecture — shared services, request strategy, paging, batching — rather than merely raising retries and watching throttling arrive.
Large SharePoint list problem
Slow requests, incomplete UIs, threshold and query issues, and browser memory pressure trace to query design: filters, indexes where applicable, field selection, paging, search-backed retrieval, and data architecture that never loads estates into memory. Verify exact platform limits before publishing numbers — this guide states none, because behavior follows indexes, views, and query shape.
Works for admin, fails for users
Permission difference, full stop — then its details: SharePoint permission, Graph scope and user access, API authorization, list and library permission, unique breaks, group membership, tenant policy. Admin-only testing hides permission problems by construction, so persona testing is the fix and the prevention at once.
- Admin works, user fails — access gap confirmed.
- Permission difference — mapped across every layer.
Works on one site, fails on another
List and library existence, IDs, URLs, permissions, site features, solution deployment, configuration, API permissions, and data structure all vary per site. Hard-coded site assumptions cause most instances — externalize per-site values and verify each target independently.
Works in one tenant, fails in another
App Catalog state, API approvals, tenant policies, Graph permissions, Entra configuration, solution versions, environment configuration, SharePoint structure, and external API configuration all differ per tenant. Never assume tenant environments are identical — diff them like distinct systems, because they are.
Browser console diagnostics
Read runtime exceptions, failed imports, React errors, CORS messages, and unhandled promises as primary evidence — never dismiss warnings indiscriminately, since today's warning names tomorrow's breaking change. The console is the cheapest diagnostic instrument available; use it before every other tool.
Network tab diagnostics
Inspect request URL, method, status, response, timing, and request and response headers per failing call. When sharing screenshots or logs, redact authorization tokens, cookies, and sensitive request bodies first — evidence shared carelessly becomes credential exposure.
HTTP status quick reference
| Status | Usually means | Check first |
|---|---|---|
| 400 | Request or query problem | Syntax, parameters, payload shape |
| 401 | Authentication or context | Sign-in, token, audience, context |
| 403 | Authorization or permission | Access, scopes, approval, policy |
| 404 | Resource or path | IDs, endpoints, context, deletion |
| 409 | Conflict where relevant | Concurrent modification, versioning |
| 429 | Throttling | Volume, guidance, backoff, reduction |
| 5xx | Server or service-side failure category | Service health, then request validity |
Diagnostic starting points, never universal root causes — each status opens an investigation rather than closing one.
Correlation and request IDs
Microsoft 365 and API responses often carry identifiers that tie client failures to server-side diagnostics and support cases. Capture them routinely and store them with error reports — while keeping sensitive logs out of public channels. An ID turns "it broke" into a traceable incident.
Logging that helps
Log operation, timestamp, error category, status, relevant correlation or request IDs, environment, and solution version — structured enough to query, restrained enough to store safely. Never log tokens, secrets, passwords, sensitive user data, or entire confidential payloads. Logging discipline is supportability.
Do not debug by random package upgrades
Error, upgrade Node, upgrade React, upgrade PnPjs, upgrade everything, more errors — this anti-pattern converts one diagnosed problem into an unmapped dependency landscape. Identify the failing layer, verify compatibility, change one controlled variable, retest. Upgrades are planned maintenance with rollback notes, never diagnostic confetti.
Do not use force flags as the first fix
npm flags that bypass dependency checks can produce a superficially successful install over an unsupported dependency graph — green terminal, broken runtime. Understand the conflict and assess compatibility first; overrides belong only to developers who can state exactly what they are overriding and why it is safe.
Do not delete the lock file first
Lock files pin reproducible dependency resolution across machines and time. Deleting one invites new versions that widen failures and destroy reproducibility. Check source control and compatibility first; lock-file changes are deliberate, reviewed, committed actions — never frustration edits.
Source control diagnostics
When something recently broke, interrogate history: package.json and lock-file changes, configuration, Node and toolchain config, source code, manifest, and solution packaging configuration — through diff and log, never through resets that discard developer work. Version control remembers what memory cannot.
Minimal reproduction
Reduce difficult failures to one component, one API call, one environment, one failing scenario. Isolation distinguishes framework, dependency, permission, API, and business-logic causes faster than any amount of full-solution debugging. Never rebuild the entire solution before isolating the problem — reproduction first, reconstruction never.
Diagnostic matrix
| Symptom | Likely layer | First check | Next action |
|---|---|---|---|
| npm install fails | Environment | Node and npm versions | Read first error, align runtime |
| Build fails | Build | First meaningful error | Fix root cause, rebuild |
| Cannot find module | Dependencies | Declaration, install, import, casing | Correct the reference chain |
| TypeScript error | Build | Contract versus installed types | Adapt code, never default to any |
| Local dev fails | Development | Server output, cert trust, ports | Fix environment, retry |
| Web part not in toolbox | Deployment | Package, availability, manifest, scope | Complete the deployment chain |
| Package not generated | Package | Build success, config, toolchain | Satisfy prerequisites in order |
| Package not available | Deployment | Catalog, deployment, scope | Finish distribution steps |
| New version not appearing | Deployment | Version, catalog state, environment | Verify before blaming caches |
| PnPjs 403 | Authorization | Effective user access | Fix access or scope, retest as user |
| PnPjs 404 | Data | Site, list, path, environment | Verify the actual target |
| Graph 401 | Identity | Token, audience, context | Fix sign-in before scopes |
| Graph 403 | Authorization | Endpoint, scope, approval, access | Work the 403 chain |
| Graph 429 | Network | Volume and guidance | Honor guidance, reduce volume |
| Graph results incomplete | Data | Next-link handling | Page every collection |
| CORS | Network | Server allowed origins | Fix server-side or mediate |
| Works as admin only | Authorization | Permission differences | Test every persona |
| Works in dev only | Production | Environment diff | Align configuration and access |
| Works in one tenant only | Production | Catalog, approval, policy | Diff tenants as systems |
| Slow web part | Performance | Network tab evidence | Fix data patterns first |
| Too many API calls | Performance | Effects, sharing, N+1 | Redesign fetching architecture |
Troubleshooting flowchart
- SPFx problem — symptom captured exactly.
- Does the project build? — no goes to environment, Node, npm, TypeScript, dependencies.
- Does the package deploy? — no goes to package, App Catalog, version, deployment.
- Does the component load? — no goes to manifest, runtime, React, dependency.
- Does data load? — no goes to REST, PnPjs, Graph, API.
- User-specific failure? — yes goes to permissions, identity, tenant policy.
- Production-only? — yes goes to configuration, deployment, environment, scale.
Quick checklist
Environment: SPFx version identified; compatible Node version; npm version known; dependencies installed consistently.
Build: first meaningful error identified; TypeScript errors resolved; package compatibility checked.
Deployment: correct package; correct App Catalog; version verified; deployment verified.
Runtime: console checked; network checked; correct configuration; correct site and resource.
Data: REST and PnPjs context correct; internal field names verified; paging considered.
Graph: endpoint verified; minimum permission identified; permission requested; permission approved; user access tested; throttling handled.
Security: no secrets in browser; tokens not logged; least privilege applied.
Production: standard user tested; environment values verified; data volume tested; solution version confirmed.
Still troubleshooting a complex SPFx issue
If the problem involves SPFx architecture, deployment, Microsoft Graph permissions, PnPjs, external APIs, authentication, or a production-only failure, share the environment, error, and expected outcome with nextM365: Discuss Your SPFx Issue.
Continue with Explore SPFx, the SPFx complete guide, SPFx and React, SPFx and PnPjs, and SPFx and Microsoft Graph.
Related resources
Topics covered
React · Project Structure · Permissions · ALM · Security
Frequently asked questions
Why does my SPFx project fail after upgrading Node.js?
Each SPFx release supports specific Node.js LTS versions. Upgrading Node beyond the supported range breaks the toolchain, so match Node to the SPFx release and use a version manager when maintaining multiple SPFx generations.
Why does npm install fail in an SPFx project?
Work the order: Node version, npm version, package.json, lock file, then the first meaningful npm error. Dependency conflicts usually trace to React, Fluent UI, or SPFx version mismatches — never force-install past them without understanding compatibility.
Why can’t SPFx find a module?
Check the dependency declaration, installation state, import path and casing, package renames across major versions, version mismatch, and missing type declarations — in that order, before reinstalling anything.
Why is my SPFx Web Part not appearing?
Verify package deployment, solution availability to the site, component type, manifest validity, feature and site deployment configuration, tenant-wide behavior, and page-context support — uploading alone never proves availability.
Why does SPFx work locally but not in production?
Compare configuration, identity, permissions, data, deployment, and network between environments. Tenant URLs, list IDs, API endpoints, Graph approvals, user permissions, App Catalog state, and data volume all differ — diff them systematically.
Why does PnPjs return 403?
Almost always authorization: the current user lacks rights, the operation needs greater permission, the wrong resource was addressed, or a Graph call lacks an approved scope. Verify effective access first — PnPjs never bypasses SharePoint permissions.
Why does Microsoft Graph return 403 in SPFx?
Work the chain: exact endpoint, required permission, requested scope, admin approval state, user and resource access, tenant policy — then retest. Most Graph 403s are unrequested scopes, unapproved grants, or access gaps.
Why does Graph Explorer work but SPFx fail?
Different permission grants, application identities, user consent, and token contexts. Explorer success validates the endpoint and query only — never the SPFx solution’s permissions, which need separate verification.
Why does Microsoft Graph return 429?
Throttling from excessive request volume. Honor the server’s retry guidance, wait, retry appropriately, then reduce volume through select, paging, batching, caching, and debounced search — never hammer throttled endpoints.
Why does my SPFx external API call fail with CORS?
The browser blocks cross-origin calls the API has not allowed. Fix allowed origins server-side or route through a mediated backend — never disable browser security, use insecure proxies, or embed credentials to work around it.
Why does SPFx work for administrators but not normal users?
Permission differences across SharePoint access, Graph scopes and user access, API authorization, list permissions, unique breaks, group membership, or tenant policy. Admin-only testing hides these by construction — test every persona.
Should I delete node_modules and package-lock.json to fix SPFx?
No — not first. Lock files pin reproducible dependency graphs, and deleting one can introduce new versions that widen the failure. Diagnose the layer, compare source control, and treat lock-file changes as deliberate, reviewed actions.
Should I use npm --force to fix dependency errors?
No — not as a first fix. Force flags can produce a superficially successful install over an unsupported dependency graph. Understand the conflict and assess compatibility first; use overrides only deliberately.
Sources
Have a Microsoft 365 topic idea?
Share article suggestions, community session ideas, corrections, or real-world scenarios for future nextM365 learning notes.
Keep learning Microsoft 365
Explore more practical tutorials for SharePoint, Power Platform, Copilot Studio, migration, automation, governance, and security.
Continue learning
Related tutorials