Troubleshooting¶
This page starts from what you see, a missing graph, an error code or a slow
run, and says what usually causes it and what to change. Before changing
anything, read the run manifest (<name>.run.json from ontocast process
--output-dir) or the metadata of the /process response: it records the
settings the run used, so it separates "the model did badly" from "that stage
never ran".
| Symptom | Likely cause | What to change or check |
|---|---|---|
422 from /process, or no facts at all |
Every part failed, the document did not convert, or facts were never requested | No facts, or a 422 |
Run stops with EmptyOntologyContextError |
A part was shown no ontology, and the run requires one | Empty ontology context |
| Facts-only run produced almost nothing | Empty catalog, or a fixed ontology id that matches nothing | Facts-only run produced nothing |
| New terms invented instead of yours | Catalog not loaded, or the wrong ontology shown to each part | Extraction ignores my ontology |
| Duplicates survive, or distinct entities are merged | Disambiguation threshold | Duplicate entities or wrong merges |
| SHACL violations, or SHACL never runs | Shapes or the shacl extra missing; violations the autofix cannot repair |
SHACL violations |
429 errors from the provider, or slow runs |
Concurrency above the provider's limits | Rate limits and slow runs |
| A setting has no effect | Not in the process environment, or overridden | Settings seem ignored |
409 with VECTOR_STORE_UNAVAILABLE |
Vector store not configured or not initialized | Vector mode returns 409 |
| Model output does not parse | A syntax error the parser could not repair | llm/parse_retry and llm/parse_abandoned in budget.counters; see How LLM responses are parsed |
| Warning that the ontology context is still over budget | The ontology is too large to show whole | Split the catalog, or switch to selected_vector_search_ontology; see Choosing ontology context |
| Parts split mid-argument, or too coarse | Chunk size bounds | CHUNK_MIN_SIZE, CHUNK_MAX_SIZE |
| Reference list extracted as domain facts | Bibliography routing | CHUNK_BIBLIOGRAPHY_MODE |
Gaps inside words in PDF text (di ff usion) |
Ligature repair | CONVERTER_REPAIR_LIGATURE_GAPS=true |
| A born-digital PDF converted as if scanned, or the reverse | Converter profile | Fix CONVERTER_PROFILE to fast or ocr |
Equations missing from the text (<!-- formula-not-decoded -->) |
Formula decoding is off | CONVERTER_PROFILE=lean, or CONVERTER_DO_FORMULA_ENRICHMENT=true; conversion slows with each equation |
| Memory use higher than expected | Several local embedding models loaded | Performance tuning |
No facts, or a 422¶
/process answers 422 when no part of the document produced output. The
body says why. With error_code no_units_extracted, error_details gives the
failing stage and reason, and unit_failures lists each part that failed; a
document that could not be converted fails here too. An error_code starting
with empty_section_selection means target_sections or exclude_sections
left nothing to process. /process_unit reports a conversion failure as
conversion_failed.
For a conversion failure, check the file type against input_types in GET
/info: converted formats need the doc-processing extra, and
CONVERTER_SUPPORTED_EXTENSIONS
may narrow them.
A 200 with an empty data.facts has different causes:
RENDER_MODE=ontology, which never extracts facts.metadata.chunks_remainingis0and the run manifest showsrender_mode.- Some parts failed.
metadata.failed_unitslists them with the stage and reason. - Facts-only run against an empty or wrong catalog; see below.
Empty ontology context¶
Each part of a document (content unit) is shown a slice of your ontologies, its ontology context. When that slice is empty, an ontology part creates a new ontology from the text, which is how OntoCast starts without a catalog. A facts part has nothing to do that with: it falls back on generic vocabulary.
With ONTOLOGY_CONTEXT_REQUIRED=true
an empty context for a facts part stops the run with EmptyOntologyContextError
instead. The message names the cause; retrieval_metrics.empty_snapshot_reason
records it too. The usual causes:
- The catalog is empty. The startup log names the seed directory OntoCast used and ends the sync with
Ontology sync finished: N ontolog(ies). - In fixed mode, the id matches no ontology; see below.
- In vector mode, the index and the catalog disagree: the index holds ontologies while the triple store holds none, or the other way round. OntoCast refuses to start in both cases. Load the ontologies into the triple store, or rebuild the index with
--wipe-vector-store.
Facts-only run produced nothing¶
With RENDER_MODE=facts no ontology terms are created, so the run depends
entirely on the catalog. Two configurations produce almost nothing without
failing:
- An empty catalog.
ontocast processlogs a warning and extracts in generic vocabulary. Seed the catalog with--ontology-dirorONTOCAST_ONTOLOGY_DIRECTORY, or runontology_and_factsonce. - A fixed id that matches nothing. In
fixed_single_ontologymode, an id that names no ontology logsNo catalog ontology match for ontology_context_fixed_ontology_idand continues with an empty ontology. The id can be the ontology's IRI, its ontology id or its prefix. Check it after renaming an ontology.
Set ONTOLOGY_CONTEXT_REQUIRED=true to turn both into errors: ontocast
process then refuses to start on an empty catalog, and a part with no ontology
context stops the run.
Extraction ignores my ontology¶
When the output invents terms that your ontology already has:
- Check the catalog loaded. The startup log names the seed directory, or says none is configured, and reports how many ontologies the sync found. A directory that does not exist stops
ontocast processand only warns underontocast serve. On a server, a request with?tenant=or?project=reads a different partition from one without, so an ontology uploaded to one is not seen by the other. - Check which ontology each part saw. In the default
selected_single_ontologymode the model picks one ontology per part, and may pick another or none. Steer it withontology_selection_user_instruction(see Writing user instructions), fix the ontology withfixed_single_ontology, or switch toselected_vector_search_ontologywhen parts need terms from several ontologies. - Check the context fits.
retrieval_metrics.ontology_snapshot_triplesis the size of the slice shown.ONTOLOGY_CONTEXT_MAX_TRIPLEScaps it; over the cap, comments and definitions go first. In vector mode, raiseVECTOR_STORE_TOP_KorVECTOR_STORE_INDUCED_SUBGRAPH_MAX_TOTAL_TRIPLES.
Facts always go in the cd: namespace, typed with your ontology's classes.
A cd: entity is expected; a cd: class or property is not. See Ontologies
and facts.
Duplicate entities or wrong merges¶
The same entity extracted from several parts is merged when the labels are
similar enough and no guard objects.
AGG_CANDIDATE_SIMILARITY_THRESHOLD
sets how similar:
- Duplicates survive: lower it.
- Distinct entities are merged: raise it, and keep
AGG_LITERAL_CONFLICT_GUARDandAGG_INITIALS_DISTINCT_GUARDon.
AGG_SIMILARITY_THRESHOLD does not affect this: it is only a fallback for
matching entities across graphs.
retrieval_metrics.facts_rejected_merges counts merges the guards refused.
Entity disambiguation explains the
guards.
SHACL violations¶
If metadata.facts_conformance.shacl_evaluated is null, SHACL never ran:
no shapes were loaded for the partition, or the shacl extra is not
installed. Load shapes with FACTS_SHAPES_DIR, --shapes-dir or POST
/shapes. POST /flush keeps shapes unless you pass include_shapes=true.
When SHACL runs and reports violations:
metadata.facts_validation_findingslists each one, andmetadata.facts_gate_repairswhat was repaired.FACTS_SHACL_AUTOFIXrepairs what it can without an LLM call (pruneby default). It never invents a value, so a node with real data but a missing required property stays a finding.- The model is shown the shapes by default, so it can extract conforming facts in the first place. Check that
FACTS_SHAPES_PROMPT_CONTRACTis notoff. FACTS_CRITIC_PASSESsets how many review calls each part gets; the critic runs once by default. Validation layers explains what it sees and when it stops.
Validation and SHACL covers shapes and the gate in full.
Rate limits and slow runs¶
PARALLEL_WORKERS
parts of one document run at once, and
LLM_MAX_INFLIGHT caps
the calls in flight across all documents. When the provider answers 429:
- Lower
LLM_MAX_INFLIGHT. LoweringPARALLEL_WORKERSalone does not help a server that runs several documents at once. - Set
LLM_REQUESTS_PER_SECONDto your provider tier's rate; a burst of short calls can exceed it with few calls in flight. - Raise
LLM_MAX_RETRIES: the provider SDK retries with backoff. OntoCast does not retry rate-limited calls itself.
llm/rate_limited in budget.counters counts the throttles that got through.
For slow runs, the budget shows where the time went: node_durations per
stage and calls_count against cache_hits. A hung call holds a worker until
LLM_REQUEST_TIMEOUT_SECONDS.
Each extra review or completion pass adds a call per part. Performance
tuning explains the concurrency layers and what to measure.
Settings seem ignored¶
- The settings file is not read. OntoCast reads a file only when it is passed with
ontocast --env-file FILE; otherwise it reads the process environment alone. A variable exported in the shell wins over the file. - The server reads settings once. Restart
ontocast serveafter a change. - A request overrides it.
render_mode,ontology_context_mode,ontology_context_fixed_ontology_id,llm_graph_formatandmax_visitssent with a request win over the environment. - Dataset names come from the tenant and project.
ontocast serveandontocast processname the Fuseki datasets and vector collections after the tenant and project (--tenant,--project), whateverFUSEKI_DATASETor a table setting says, and log a warning naming the ignored setting. See Tenancy. - Fixed mode needs the mode setting. For
ontocast process, setONTOLOGY_CONTEXT_MODE=fixed_single_ontologyas well asONTOLOGY_CONTEXT_FIXED_ONTOLOGY_ID. - The name is wrong. An unknown variable in the environment is ignored without a warning.
ontocast config check FILEnames the unknown variables in a settings file, and--env-filewarns about them at startup; the run manifest shows the values the run used.
Fuseki refuses the connection¶
FusekiAccessError: ... answered 401 creating dataset means the server wants
credentials OntoCast did not send, or rejected the ones it did. Set
FUSEKI_AUTH to a user with admin rights, or allow anonymous access in the
server's shiro.ini. See Triple stores.
Vector mode returns 409¶
409 with error_code: VECTOR_STORE_UNAVAILABLE means the request asked for
selected_vector_search_ontology and this server has no working vector store.
The error text includes the last initialization error, if there was one.
- None configured. Set
LANCEDB_ENABLED=true(lancedbextra) orQDRANT_URI(qdrantextra). - Configured but never initialized. The index is built at startup only when the server starts in vector mode. To send vector-mode requests, start the server with
ONTOLOGY_CONTEXT_MODE=selected_vector_search_ontology. - Initialization failed. A Qdrant server that is down, or embedding settings that do not match the stored index. After changing
EMBEDDING_MODEL_NAME,EMBEDDING_DIMENSIONor the query and document prefixes, restart with--wipe-vector-storeto rebuild the index.
Choosing ontology context explains when vector mode is worth setting up.