Exa Known Pitfalls
Overview
Real gotchas when integrating Exa's neural search API. Exa uses embeddings-based search rather than keyword matching, which creates a different class of failure modes than traditional search APIs. This skill covers the top pitfalls with wrong/right examples.
Pitfall 1: Keyword-Style Queries
Exa's neural search interprets natural language semantically. Boolean operators and keyword syntax degrade results.
import Exa from "exa-js";
const exa = new Exa(process.env.EXA_API_KEY);
const bad = await exa.search(
"python AND machine learning OR deep learning 2024"
);
const good = await exa.search(
"recent tutorials on building ML models with Python",
{ type: "neural", numResults: 10 }
);
Pitfall 2: Wrong Search Type
Using neural search for exact lookups (URLs, names) or keyword search for conceptual queries silently degrades quality.
const bad = await exa.search("arxiv.org/abs/2301.00001", { type: "neural" });
const exactMatch = await exa.search("arxiv.org/abs/2301.00001", {
type: "keyword",
});
const conceptual = await exa.search(
"transformer architecture improvements for long context",
{ type: "neural" }
);
Pitfall 3: Expecting Content from search()
search() returns metadata only (URL, title, score). Content requires searchAndContents() or getContents().
const results = await exa.search("AI safety research");
const text = results.results[0].text;
const withContent = await exa.searchAndContents("AI safety research", {
numResults: 5,
text: { maxCharacters: 2000 },
highlights: { maxCharacters: 500 },
});
console.log(withContent.results[0].text);
console.log(withContent.results[0].highlights);
Pitfall 4: Narrow Date Filters Return Empty
Date filters silently exclude results. A single-day window often returns nothing without error.
const bad = await exa.search("AI news", {
startPublishedDate: "2025-03-15T00:00:00.000Z",
endPublishedDate: "2025-03-15T23:59:59.000Z",
});
let results = await exa.search("AI news", {
startPublishedDate: "2025-03-01T00:00:00.000Z",
endPublishedDate: "2025-03-31T23:59:59.000Z",
numResults: 10,
});
if (results.results.length === 0) {
results = await exa.search("AI news", { numResults: 10 });
}
Pitfall 5: findSimilar Takes a URL, Not a Query
findSimilar expects a URL as its first argument. Passing a query string gives meaningless results.
const bad = await exa.findSimilar("machine learning research papers");
const good = await exa.findSimilar("https://arxiv.org/abs/2301.00001", {
numResults: 10,
excludeSourceDomain: true,
});
Pitfall 6: Date Filters with company/people Categories
The company and people categories do NOT support date filters. Using them returns a 400 error.
const bad = await exa.search("AI startups", {
category: "company",
startPublishedDate: "2024-01-01T00:00:00.000Z",
});
const good = await exa.search("AI startups", {
category: "company",
numResults: 10,
});
Pitfall 7: Not Limiting Content Size
Requesting full text without maxCharacters can return massive payloads, increasing latency and cost.
const bad = await exa.searchAndContents("topic", {
numResults: 20,
text: true,
});
const good = await exa.searchAndContents("topic", {
numResults: 10,
text: { maxCharacters: 2000 },
highlights: { maxCharacters: 500 },
});
Pitfall 8: Creating New Client Per Request
Each new Exa() call creates a new HTTP client. Reuse a singleton for connection pooling.
app.get("/search", async (req, res) => {
const exa = new Exa(process.env.EXA_API_KEY);
const results = await exa.search(req.query.q);
res.json(results);
});
const exa = new Exa(process.env.EXA_API_KEY);
app.get("/search", async (req, res) => {
const results = await exa.search(req.query.q);
res.json(results);
});
Pitfall 9: Ignoring the requestId in Errors
Exa error responses include requestId for support debugging. Always log it.
try {
await exa.search("query");
} catch (err) {
console.error("Search failed");
}
try {
await exa.search("query");
} catch (err: any) {
console.error("Search failed:", {
status: err.status,
message: err.message,
requestId: err.requestId,
tag: err.error_tag,
});
}
Quick Review Checklist
Resources
Next Steps
For SDK patterns, see exa-sdk-patterns. For common errors, see exa-common-errors.