Documentation menuTroubleshooting
Troubleshooting
Symptoms and fixes for missing results, a model that does not load, CORS, base paths, large indexes and hidden filters.
Open the browser console first. Cosine logs errors there with the prefix cosine:.
No results
Check these in order:
- The build found your pages.
cosine buildprintsIndexed 42 pages as 186 chunks. If the number is 0 or too low, check the directory you passed, the file extensions (.md,.mdx,.markdown,.html,.htm,.txt), your--excludeoptions, and whether HTML pages have<meta name="robots" content="noindex">(they are skipped). - HTML pages have content in
<main>. Cosine reads<main>, then<article>, then<body>. Elements withdata-cosine-ignoreare dropped. - The index is found. Open
/cosine/cosine-index.jsonin the browser. A 404 shows up in the console ascosine: could not load ... (404), and a missingindexattribute ascosine-search: missing index attribute. - No
scopelimits the search. Ascopeattribute or option hides everything outside those paths. - The query is not only an exclusion.
-retryalone has nothing to find. Add a word that should match. - The semantic ranking does not cut your query. Semantic hits below the minimum similarity are dropped, so nonsense finds nothing. Try the same query with
mode="lexical"; if that finds results, lowerminSimilarityinloadIndex(see Models).
Try the query in the terminal: npx cosine search public/cosine "your query" --mode lexical.
Only keyword results, the model never loads
The status of the search is lexical until the model is requested, then loading-model and ready, or model-failed. Reasons for staying on keywords:
- The browser asks to save data. With
load-model="lazy"(the default), Cosine stays lexical when the visitor has "save data" turned on. Useload-model="eager"to load the model anyway. load-model="never",mode="lexical"or an index built with--lexical-only. These never load a model, on purpose.- A Content Security Policy blocks the download. The model comes from
huggingface.co, and transformers.js loads its WebAssembly runtime from a CDN. The console shows a CSP violation. Allow the hosts inconnect-src, allow WebAssembly inscript-src('wasm-unsafe-eval') and, if needed, the CDN for scripts. Or serve both yourself, see Privacy and self-hosting, and the policy can stay strict. - The visitor is offline or the host is blocked (a company firewall, a privacy extension). The status becomes
model-failedand keyword search keeps working. @huggingface/transformersis not installed in the project that bundles the search.
The index files fail to load from another domain (CORS)
The browser fetches cosine-index.json and the vector file with fetch. From another origin (for example a CDN domain) the server must send Access-Control-Allow-Origin for your site. The simplest fix is to serve the index from the same domain as the page. If you use a CDN, add the header there, for both files.
Results link to the wrong page, or the index is not found
- The
indexattribute is a URL as the browser sees it. If the site lives below/docs/, useindex="/docs/cosine/cosine-index.json"and make sure the files are actually served there. Relative URLs depend on the current page, so prefer absolute paths. - The links in the results come from the build:
--base-url /docsmakesguides/cli.mdlink to/docs/guides/cli. Set it to the path where the pages are served, or the clicks end in 404 pages. - With a framework that adds a
trailingSlashor.htmlsuffix, check one result URL in the console (cosine-resultsevent) against the real page URL. If they differ, build from the generated HTML instead of the sources, since Cosine mapsabout/index.htmlto/about/. - Use
cosine-selectwithpreventDefault()to navigate with your router when the site is a single page application, see Search field.
The index is too large
Check the size of public/cosine first, and compare it with Performance: the vectors need about 390 bytes per section, the manifest also contains the text of every section.
- Exclude pages nobody searches:
--exclude drafts/,--exclude changelog/. - Raise
--max-charsto get fewer, longer sections (the default is 1200). - Build with
--lexical-onlywhen you do not need the model: no vector file, no model download. - Serve the files compressed (gzip or Brotli). The JSON compresses very well.
- If the site has tens of thousands of pages, Cosine is the wrong tool, see Why Cosine.
"the index has N chunks but M vectors" or "built with X, the embedder uses Y"
Both errors mean that cosine-index.json and the vector file do not belong together, or the model does not match the vectors.
- Different builds. A CDN or the browser cache served an old vector file next to a new manifest (or the other way round). Deploy both files together and purge the cache for both.
- Different model. The index stores the model id. A custom
embeddermust use the same model as the one the index was built with. Rebuild with the model you want to use at search time. - Different prefixes. For E5 and BGE models, build and search with the same
--query-prefixand--passage-prefix, they are stored in the index. - When in doubt, rebuild:
npx cosine build docs --out public/cosine(without--incremental).
The filter buttons do not show
- The
facetsattribute (or prop) must be set on<cosine-search>. - With a single section in the results there is nothing to filter, so the buttons stay hidden. Search for a word that appears in more than one section.
- Filters are per section of the URL path. If all your pages share the first path segment (
/docs/...), usefacets="2"to filter by the first two (/docs/guides,/docs/api). - Custom CSS can hide them. They are exposed as
::part(facets).
Changes to the pages do not show up in search
The index is built at build time. Run cosine build again before you deploy, and make sure the build runs after the site is generated if you index built HTML. A browser may hold an old cosine-index.json in its cache; a hard reload fixes it, and your host's cache headers decide how long it lasts for visitors.
Still stuck?
Open an issue at github.com/Weber-Development/cosine with the console output, the output of cosine build and the version of @sweberdev/cosine.