Excel: XLOOKUP returns #N/A
Hi, it's BlueByte. When XLOOKUP returns #N/A, the formula itself is fine — it searched the lookup range and simply didn't find the value you asked for. The symptom is a cell showing #N/A (or a whole spilled column of them) where you expected a matched result. We'll walk through what #N/A means here, the handful of reasons a lookup finds nothing, how to confirm which one you hit, fix each cause, and how to show a useful message instead of the raw error.
What #N/A from XLOOKUP means
#N/A means "no value is available" — the lookup ran and found no match. By default XLOOKUP uses exact matching, and Microsoft's documentation is explicit: if a valid match is not found and if_not_found is omitted, #N/A is returned. The full signature is:
=XLOOKUP(lookup_value, lookup_array, return_array, [if_not_found], [match_mode], [search_mode])With match_mode omitted it defaults to 0 (exact match), so if nothing in lookup_array equals lookup_value exactly, you get #N/A. That is different from a structurally broken formula — this one ran correctly and is telling you the value isn't there.
The reasons an exact-match lookup finds nothing
An exact-match #N/A comes from one of these:
- The value genuinely isn't in the lookup range.
- The value is there but has extra spaces or non-printing characters on one side, so the two strings aren't equal.
- A number is stored as text on one side and as a real number on the other —
"12345"never equals12345. - You pointed
lookup_arrayat the wrong column, or the range doesn't cover every row.
Each of these breaks the exact-match test that match_mode 0 performs; none is a bug in XLOOKUP.
Confirm which reason with a few quick checks
Don't guess — a couple of helper formulas tell the causes apart. Check whether the value exists at all, and whether the text lengths differ (a length gap means hidden spaces):
=COUNTIF(A:A, D2)
=LEN(D2) & " vs " & LEN(A2)If COUNTIF returns 0, the value truly isn't found (or a type/space mismatch is hiding it). If the two LEN values differ for what looks like the same text, you have stray spaces. Then check the data type on each side:
=ISNUMBER(D2) & " / " & ISNUMBER(A2)If one is TRUE and the other FALSE, you're comparing a number to text — that's your #N/A.
Fix it by cleaning the lookup value
For stray spaces or non-printing characters, wrap the lookup value in TRIM (removes extra spaces) and, if needed, CLEAN (removes non-printable characters):
=XLOOKUP(TRIM(D2), A2:A100, B2:B100)Expected result: the lookup that returned #N/A now returns the matched value, because TRIM(D2) equals the stored key exactly. If the source data carries the spaces, clean that column once rather than wrapping every formula.
Fix a number-stored-as-text mismatch
If one side is text and the other a real number, make them the same type. To coerce a text lookup value to a number:
=XLOOKUP(VALUE(D2), A2:A100, B2:B100)If instead the keys are text and your lookup value is numeric, coerce the other way with D2 & "". The durable fix is to store the key column consistently — select it and run Data ▸ Text to Columns ▸ Finish to convert text-numbers to real numbers in place.
Show a friendly message instead of #N/A
Once you've confirmed a blank result is legitimate — the value really can be missing — don't leave a raw #N/A on the sheet. XLOOKUP has a built-in if_not_found argument for exactly this:
=XLOOKUP(D2, A2:A100, B2:B100, "Not found")That returns Not found instead of #N/A when there's no match. For an existing formula you'd rather not rewrite, wrap it in IFNA, which traps only #N/A and passes every other result through unchanged:
=IFNA(XLOOKUP(D2, A2:A100, B2:B100), "Not found")Prefer IFNA over IFERROR here: IFERROR also hides #REF!, #VALUE!, and #DIV/0!, which would mask a genuine formula bug.
A real case: an order ID that looks equal but isn't
You're matching order IDs. =XLOOKUP(D2, A:A, B:B) returns #N/A, yet D2 and A47 both read ORD-1001. You run =LEN(D2)&" vs "&LEN(A47) and get 8 vs 9 — A47 picked up a trailing space from an export. You add a helper column =TRIM(A2), point the lookup at that cleaned column, and the #N/A becomes the correct customer name. The length check now reads 8 vs 8, confirming the keys finally match.
Verify the match and prevent it recurring
Confirm the fix with the same checks you started with — COUNTIF should now return 1 (or more) and the two LEN values should agree. To keep it from returning: hold key columns in one consistent data type, TRIM imported data as it comes in, and add a permanent if_not_found message so a future missing value shows text rather than a red error. If your keys are clean, leave match_mode at the default 0 and rely on exact matching instead of approximation.
How #N/A differs from #REF! and a silent VLOOKUP
#N/A means the lookup ran and found nothing. #REF! is different: a cell reference in the formula points at something that no longer exists — a deleted row or column — so the formula can't resolve its own inputs. And watch for the opposite of #N/A: VLOOKUP with its fourth argument left as TRUE (approximate match) returns the nearest value instead of #N/A when there's no exact match — a wrong answer with no error at all. XLOOKUP defaulting to exact match is safer precisely because it surfaces #N/A instead of quietly guessing.
Related questions
Why does XLOOKUP show #N/A when I can clearly see the value in the list?
Almost always a hidden mismatch — a trailing space or a number stored as text. Compare LEN() on both cells and ISNUMBER() on each; if either differs, that's the cause.
Should I use if_not_found or IFNA?
If you're writing the XLOOKUP now, use its built-in if_not_found argument. Use IFNA to wrap an existing formula you don't want to rewrite. Prefer either over IFERROR, which also hides real errors like #REF! and #VALUE!.
Does changing match_mode fix #N/A?
Setting match_mode to -1 or 1 returns the nearest smaller or larger value instead of #N/A, but that's an approximate match. Use it only when 'closest' is genuinely what you want, such as tax brackets — not to paper over a mismatch.
My lookup value is a number but the keys are text — what's fastest?
Coerce in the formula with D2 & "" for a quick fix, or convert the key column to a consistent type with Data ▸ Text to Columns for a permanent one.
Can XLOOKUP return #N/A even with if_not_found set?
No. If if_not_found is supplied, a no-match returns that text, not #N/A. If you still see #N/A, it's coming from another part of the formula, not the missing match.
References
Haneul Seo
Infrastructure engineer · 10+ years running Linux fleets
More in this category
Gmail rejects your mail with 550-5.7.26: unauthenticated email is not accepted due to the domain's DMARC policy
Gmail enforced the DMARC policy your own domain publishes: the message failed both SPF and DKIM alignment against the header From: domain, so a p=quarantine or p=reject policy turned it into a hard bounce. The Authentication-Results header names the failing check, and three dig queries against your SPF, DMARC and DKIM records name the cause. A near-identical bounce about authenticating with SPF or DKIM is a different problem — Gmail's baseline sender requirements, not your policy.
Microsoft Entra ID: AADSTS50011, the redirect URI specified in the request does not match the redirect URIs configured for the application
Sign-in completes and then Entra ID refuses the last hop, because the redirect_uri your app sent is not a byte-for-byte match for any URI registered on the app. The match is case-sensitive, counts the trailing slash, requires https outside localhost, and treats the port as significant everywhere except localhost. It also splits by platform: web, spa and publicClient are three separate lists, and URIs added to the service principal instead of the application object can disappear. Read the URI and the app ID out of the error, compare them with az ad app show, add the exact string with az ad app update or a Graph PATCH, then wait three to five minutes.
Exchange Online: 535 5.7.139 Authentication unsuccessful, SmtpClientAuthentication is disabled
A scanner, script or app that sends through smtp.office365.com gets 535 5.7.139 because the SMTP AUTH protocol is switched off for the tenant, for that mailbox, or by an authentication policy or security defaults that block Basic authentication. Read the wording (Tenant, Mailbox, or 'did not meet the criteria'), confirm with Get-TransportConfig, Get-CASMailbox and Get-AuthenticationPolicy, then open SMTP AUTH on the one mailbox that needs it rather than tenant-wide. Treat Basic SMTP AUTH as a bridge: Microsoft disables it by default for existing tenants at the end of December 2026, so move the sender to OAuth, High Volume Email or a relay connector.
Zoom: "Unable to connect" error code 5003 — the desktop app can't reach Zoom while the browser can
Error 5003 is the Zoom desktop app failing to complete its connection to Zoom's servers while the web client on the same machine joins fine. The app needs more than a browser does: Zoom's firewall article lists TCP 443/8801/8802 and UDP 3478/3479/8801–8810 for meetings, a set of CA hosts for certificate validation, and it asks that zoom.us and *.zoom.us be exempted from proxy or SSL inspection. A port test, a curl issuer check, and the app's built-in Network Connectivity Tool (Ctrl+Alt+Shift+D / Cmd+Option+Shift+D) show which of those is cut; fix that layer, and reinstall only when a single machine fails while its neighbours join.
Slack: "Slack cannot connect" and the grey "Last updated…" banner behind a corporate proxy
Slack loads channels over ordinary HTTPS but delivers new messages over a persistent WebSocket on port 443 to the three wss-*.slack.com hosts Slack names (primary, backup, mobile). When a proxy or firewall passes the HTTP side and blocks the upgrade — most often because SSL decryption is on for the wss hosts, or the allowlist stops at slack.com — the app shows the grey "Last updated…" banner or "Slack cannot connect." while the browser seems fine. Two curl probes from the affected machine show which layer is blocked; exempt the three wss hosts from decryption, allow every domain on my.slack.com/help/urls, and confirm with my.slack.com/help/test.
Word: "The document is locked for editing by another user"
Word found a lock — an owner file — for the document and assumed someone else has it open, so it offers only a read-only copy. Usually no one does: a crash left the lock behind, or a hidden Word process is still holding the file. Confirm which, close every Word instance, delete the stale ~$ owner file, and the document opens for editing again.