"The PDF I uploaded yesterday isn't being referenced today." If you use Claude Projects daily, you've probably hit this exact wall. There's no error, no warning — Claude just calmly replies that it doesn't have information about that. The silence is what makes it so frustrating.
So you rephrase the question. Then again. An hour disappears — an hour taken straight out of the build. As an indie developer keeping operational docs for several sites inside Projects, I've lost that hour more than once.
Eventually I changed the approach. Instead of discovering after the upload that a file can't be read, check it before it goes in. This piece covers the triage, and the diagnostic script I actually run.
Put the symptom in one of three layers
The first move is to decide which layer the problem lives in. Once the layer is settled, the fix is usually a single action.
| Layer | Typical symptom | Tell |
|---|---|---|
| Index | "No relevant information" only right after upload | Waiting a few minutes fixes it |
| File | Still unrecognized hours later | Only certain files misbehave |
| Instructions | Search works, answers ignore it | Saying "quote the knowledge" surfaces it |
If the instruction layer is at fault, rebuilding your files changes nothing. If a scanned PDF is at fault, polishing your custom instructions is wasted effort. Mixing these up is what costs a whole afternoon.
Suspect the index before the file
Uploading a file doesn't make it searchable right away. The platform chunks the document, generates embeddings, and writes them to an index. That pipeline takes time.
In my experience a clean, text-based PDF under 30 pages becomes searchable within a minute. A 100-page report packed with images can take five to ten minutes.
Symptom: asked right after upload, got "no relevant information"
Wait five minutes, then start a new conversation and ask again. The original conversation tends to inherit its earlier "I don't know" judgment even after the index catches up. Pushing harder in the same thread is the most common detour.
Symptom: hours later, still nothing
Not the index. Move to the file.
Your eyes can't see a text layer — let the machine check
The most common file-layer cause is a scanned PDF. A PDF exported from Word carries a text layer; a paper document run through a scanner is a picture. Claude Projects' knowledge search doesn't route through OCR, so a scanned PDF is never a search target in the first place.
The old check is to open the PDF and try to select text. That check has a hole in it: mixed PDFs, where the first few pages carry a text layer and the rest are scanned images, are common in real work. I once selected text on a cover page, decided the file was fine, and shipped a document whose entire body was invisible to search.
So stop looking and let the machine decide.
from pypdf import PdfReader
TEXT_PAGE_MIN = 50 # min characters for a page to count as "has text"
SAMPLE_PAGES = 5 # how many leading pages to inspect
def text_ratio(path):
"""Fraction of sampled pages that yield extractable text."""
pages = PdfReader(path).pages[:SAMPLE_PAGES]
if not pages:
return 0.0
filled = sum(
1 for p in pages
if len((p.extract_text() or "").strip()) >= TEXT_PAGE_MIN
)
return filled / len(pages)
r = text_ratio("report.pdf")
print(f"text_ratio={r:.2f}")A text_ratio of 0 means scanned; 1.0 means a real text layer. On my test fixtures, the text PDF yielded roughly 1,700 characters per page and the scanned one yielded zero. The verdict splits cleanly.
The 50-character threshold isn't arbitrary. Pages that only surrender a page number or a header come back around 10 characters — "effectively empty." Set the threshold to 1 and those pages pass, and scanned PDFs slip through.
Anything between 0 and 1.0 is the mixed PDF from earlier. A 0.4 means roughly half that document is invisible to search.
Diagnose the whole candidate folder at once
Checking files one at a time doesn't survive contact with a real workload. I run the whole folder before anything goes into a project.
Alongside the text layer, the script covers the two other causes that actually bit me: file size and character encoding.
import sys, pathlib
import chardet
from pypdf import PdfReader
MAX_MB = 20.0 # practical safety margin below the hard cap
TEXT_PAGE_MIN = 50
SAMPLE_PAGES = 5
def check_pdf(path):
try:
pages = PdfReader(path).pages[:SAMPLE_PAGES]
except Exception as e:
return f"READ_ERROR ({e.__class__.__name__}) — possibly encrypted"
if not pages:
return "EMPTY"
filled = sum(
1 for p in pages
if len((p.extract_text() or "").strip()) >= TEXT_PAGE_MIN
)
ratio = filled / len(pages)
if ratio == 0:
return "SCANNED — needs OCR (never searched)"
if ratio < 0.5:
return f"PARTIAL — only {filled} of first {len(pages)} pages have text"
return "OK"
def check_text(path):
raw = pathlib.Path(path).read_bytes()
enc = (chardet.detect(raw)["encoding"] or "").lower()
if enc.replace("-", "") not in ("utf8", "ascii"):
return f"ENCODING — detected {enc}. Convert to UTF-8"
return "OK"
for path in sorted(pathlib.Path(sys.argv[1]).iterdir()):
if path.suffix.lower() not in (".pdf", ".txt", ".md"):
continue
mb = path.stat().st_size / 1024 / 1024
if mb > MAX_MB:
verdict = f"TOO_LARGE — {mb:.1f} MB. Split by chapter"
elif path.suffix.lower() == ".pdf":
verdict = check_pdf(path)
else:
verdict = check_text(path)
print(f"{path.name:12} {mb:6.2f} MB {verdict}")Run it as python audit.py ./knowledge and you get:
ok.txt 0.00 MB OK
scan.pdf 0.00 MB SCANNED — needs OCR (never searched)
sjis.txt 0.00 MB ENCODING — detected shift_jis. Convert to UTF-8
text.pdf 0.00 MB OK
It runs on pypdf and chardet alone. A note on each verdict:
Size: well before the hard per-file cap, there's a band where processing gets unreliable. Files near the ceiling are safer split by chapter. Caps change over time, so confirm the current numbers in the Claude help center.
Encoding: the easiest one to miss. A Japanese .docx authored on a Mac, edited on Windows, and re-saved will often mangle during text extraction. Claude faithfully indexes the mangled string, so of course your search finds nothing. Pasting into plain UTF-8 text clears it. If the replies themselves are garbled, that's a different problem — see why Claude's responses cut off or come back garbled.
Encryption: PDFs carrying "no printing" or "no copying" restrictions block text extraction. The script surfaces those as READ_ERROR. Remove the password and re-upload.
When files "disappear" or the count is wrong
"I uploaded 8 files yesterday; today I see 6." It's almost always one of these.
Cause A: project storage cap exceeded
Projects have a total knowledge cap. Past it, new uploads can appear to succeed while older files get deprioritized internally and drop out of search. Delete material you've already consolidated elsewhere and make room.
Cause B: you were signed into a different account or workspace
Common if you juggle work and personal accounts. Cache and expired sessions quietly swap the active account more often than you'd think. Check the account name, then go back in.
Cause C: the project is archived
Even without archiving anything deliberately, projects untouched for a long stretch can drop off the list. Check the archived filter.
Recognized, but not used
Files uploaded, diagnostics clean, and Claude still won't reflect the knowledge in its answers. That's the third layer: instructions.
Projects carry per-project custom instructions. If yours say something like "always answer concisely," knowledge lookup gets deprioritized. Absent an explicit rule, Claude tends to make a conservative call about internal knowledge (what it learned) versus external knowledge (your files).
The project I keep operational docs in opens its custom instructions with exactly this:
Before answering, always search the documents in the project knowledge.
If the knowledge contains a relevant passage, cite it and prioritize it above all else.
That single addition changes the reference rate noticeably. As a triage rule: if appending "please cite the knowledge" by hand is the only thing that produces a correct answer, the cause is your instructions — not your files. On composing those instructions, I wrote up the approach separately in how to write Claude Projects custom instructions.
If it still won't budge
Work through these in order.
- Create a fresh project and migrate only the knowledge — a project's internal state does occasionally break. A new container sometimes clears it outright.
- Test in a new conversation, not a long-running one — a crowded context window degrades knowledge retrieval.
- Try a different browser — extensions, ad blockers especially, can collide with file upload. Check whether it reproduces in a private window.
- Record repro steps before contacting support — which file, which question, what time. Attaching the diagnostic output moves the conversation along considerably faster.
What to do next
Run the diagnostic script once against the folder you're about to load into a project. For me, SCANNED and ENCODING between them accounted for nearly every case of knowledge that wouldn't surface.
And when a symptom appears, pick a layer before you rephrase the question. Index means wait. File means diagnose. Instructions mean add a line. Just holding that order is what keeps an afternoon from vanishing.