# Troubleshooting

> Common auth, billing, push conflict, web crawl cap, glossary provisioning, and model credential failures with verification signals from tests and README constraints.

- Repository: GoogleCloudPlatform/knowledge-catalog
- GitHub: https://github.com/GoogleCloudPlatform/knowledge-catalog
- Human docs: https://grok-wiki.com/public/docs/googlecloudplatform-knowledge-catalog-9cee6ee3cba5
- Complete Markdown: https://grok-wiki.com/public/docs/googlecloudplatform-knowledge-catalog-9cee6ee3cba5/llms-full.txt

## Source Files

- `okf/README.md`
- `agents/enrichment/README.md`
- `agents/mdcode/README.md`
- `okf/tests/test_web_fetcher.py`
- `okf/tests/test_bigquery_source.py`
- `samples/discovery/README.md`
- `agents/enrichment/eval/__main__.py`

---

---
title: Troubleshooting
description: Common auth, billing, push conflict, web crawl cap, glossary provisioning, and model credential failures with verification signals from tests and README constraints.
---

When a Knowledge Catalog workflow fails, the error usually falls into one of six buckets: **credentials**, **billing project**, **`kcmd push`**, **OKF web crawl limits**, **glossary provisioning**, or **model access**. This page maps symptoms to root causes, fix steps, and how to confirm recovery using tests, eval metrics, and CLI checks.

## Symptom quick reference

| Symptom | Likely cause | First check |
| --- | --- | --- |
| `Unable to retrieve project, location, or token` | `gcloud` ADC or config incomplete | `gcloud auth application-default print-access-token` |
| BigQuery query fails on public datasets | Billing project unset or wrong | `gcloud config get-value project` or `--billing-project` |
| Drive folder appears empty during enrichment | ADC missing `drive.readonly` scope | Re-login with extended scopes |
| `Glossary '…' does not exist` on `kcmd push` | Glossary tree not provisioned in Dataplex | Create glossary/terms first, then `kcmd pull` |
| `fetch_url` returns `"max_pages reached"` | OKF web crawl budget exhausted | Lower scope or raise `--web-max-pages` |
| Judge metrics show `n/a` in eval | Vertex auth not configured | `GOOGLE_CLOUD_PROJECT` + ADC |
| Enrichment agent exits without `trajectory.json` | Missing deps or unbuilt `kcmd` | Build `agents/mdcode` and re-run |

---

## Authentication (`gcloud` ADC)

All three surfaces — **`kcmd`**, the **catalog enrichment agent**, and the **discovery agent** — rely on Google Cloud authentication. None of them embed long-lived API keys for Dataplex or BigQuery.

### `kcmd` and MCP

`kcmd` obtains tokens by shelling out to `gcloud auth application-default print-access-token` and reads the active project/region from `gcloud config`. If any of these are missing, initialization fails immediately:

```
Unable to retrieve project, location, or token. Ensure gcloud is configured.
```

<Steps>
<Step title="Configure ADC and gcloud defaults">

```bash
gcloud auth application-default login
gcloud config set project <your-project-id>
gcloud config set compute/region <your-region>   # e.g. us-central1
```

Verify:

```bash
gcloud -q auth application-default print-access-token | head -c 20
gcloud -q config get-value project
```

</Step>
<Step title="Confirm kcmd can reach the catalog">

From a workspace directory:

```bash
kcmd pull --dry-run
```

A non-zero exit with `Error pulling catalog entries:` usually indicates insufficient Dataplex IAM or an invalid `catalog.yaml` scope.

</Step>
</Steps>

### Catalog enrichment agent (Drive + Vertex)

The enrichment agent needs ADC with **both** `cloud-platform` and **`drive.readonly`** scopes. Without `drive.readonly`, Drive list calls return 403 — and the agent logs a warning that can look like an empty folder:

```
[Folder] ⚠️  Drive list failed for folder '…': 403 …
          If this is 403 insufficientPermissions, your ADC token is
          missing the drive.readonly scope — re-run: gcloud auth
          application-default login --scopes='openid,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/drive.readonly'
```

<ParamField body="Required ADC scopes" type="string">
`openid`, `https://www.googleapis.com/auth/cloud-platform`, `https://www.googleapis.com/auth/drive.readonly`
</ParamField>

### Discovery agent

The discovery sample requires APIs enabled (`dataplex.googleapis.com`, `aiplatform.googleapis.com`, `serviceusage.googleapis.com`) and IAM roles that include `dataplex.projects.search`, `aiplatform.endpoints.predict`, and `serviceusage.services.use`. Set:

```bash
export GOOGLE_CLOUD_PROJECT=<PROJECT_ID>
export GOOGLE_GENAI_USE_VERTEXAI=True
```

---

## Billing and BigQuery project

Public BigQuery datasets are readable, but **query bytes bill to the caller's project**. Both the OKF enrichment agent and sample recipes assume a billing project is configured.

### OKF enrichment agent

<ParamField body="--billing-project" type="string">
Google Cloud project to bill for BigQuery metadata queries. Defaults to the ADC default project when omitted.
</ParamField>

Prerequisites:

```bash
gcloud auth application-default login
gcloud config set project <your-billing-project>
```

Or pass explicitly:

```bash
python -m enrichment_agent enrich \
  --source bq \
  --dataset <project>.<dataset> \
  --billing-project <billing-project> \
  --out ./bundles/<name>
```

### Catalog enrichment agent — usage signal

Table and context-overlay modes optionally scan `INFORMATION_SCHEMA` for query history (`--include_usage`, default `true`). The `--usage_scope` flag controls fallback behavior:

| Value | Behavior |
| --- | --- |
| `auto` (default) | Try `JOBS_BY_PROJECT`; on permission denied, fall back to `JOBS_BY_USER` |
| `project` | Require project-wide job listing |
| `user` | Only your own queries (narrower, but always permitted) |

When `JOBS_BY_PROJECT` fails, the agent logs:

```
[bq_usage] JOBS_BY_PROJECT failed (…); falling back to JOBS_BY_USER
```

Region typos or billing-disabled projects also fall through; the fallback may still return **empty usage** rather than a hard error. If the `queries` aspect is empty after enrichment, retry with `--usage_scope=user` or `--include_usage=false`.

### Push-time queries aspect 403

If `dataplex.entryGroups.useQueriesAspect` is missing, `kcmd push` can fail with **403 on the `queries` aspect** while `overview` still succeeds. Remove `queries` from `publishing.aspects` in `catalog.yaml`, or grant the permission, then push again.

---

## `kcmd push` failures

### Glossary resources are never auto-created

`kcmd push` **does not create** `Glossary`, `GlossaryCategory`, or `GlossaryTerm` control-plane resources. It only **updates metadata** (descriptions, labels) on resources that already exist. Missing glossary nodes produce fail-fast errors such as:

- `Glossary '…' does not exist. kcmd does not create glossary resources…`
- `Glossary term '…' does not exist. kcmd does not create glossary resources…`
- `Parent glossary '…' does not exist in <project>/<location> (required by term …)`

<Steps>
<Step title="Provision the glossary hierarchy out-of-band">

```bash
gcloud dataplex glossaries create <glossaryId> \
  --project=<project> --location=<location>

gcloud dataplex glossary-terms create <termId> \
  --glossary=<glossaryId> --project=<project> --location=<location>
```

</Step>
<Step title="Pull, edit locally, then push metadata only">

```bash
kcmd init --glossary <project>.<location>.<glossaryId>
kcmd pull
# edit descriptions/labels under catalog/glossaries/
kcmd push
```

</Step>
</Steps>

`kcmd init --glossary` also fails at init time if the glossary ID or display name cannot be resolved:

```
Glossary '<id>' not found in <project>.<location> (tried ID and Display Name).
```

EntryLinks that **reference** glossary terms (for example `definition` links from BQ columns) **are** created and reconciled by `kcmd push` — the no-create rule applies only to the glossary tree itself.

### Entry group must exist before doc-mode enrichment

Doc mode requires `--entry_group` to **already exist**. The agent runs read-only `kcmd init`/`pull` and will not create the entry group:

```bash
gcloud dataplex entry-groups create <entryGroupId> \
  --project=<project> --location=<location>
```

### Reference layers are read-only

Files ending in `.ref.yaml` are **skipped during push**. If enrichment wrote only to reference files, `kcmd push` will not publish those edits. Copy changes into the editable `.yaml` / sidecar `.md` siblings instead.

### Push conflicts and `--force` (current behavior)

The Metadata-as-Code **design spec** calls for checksum-based conflict detection: push should abort when remote metadata changed, require `kcmd pull` to reconcile, and offer `--force` to override.

**Current implementation status:** `kcmd push` accepts `--force` and `--validate-only`, but conflict detection, `kcmd status`, and `validate()` are **not yet implemented** (`TODO: Handle conflicts` in the sync engine; `status()` and `validate()` throw `Not yet implemented`). Today, push failures are more often **resource errors** (missing glossary, failed EntryLink create, entry-group create denied) than checksum conflicts.

Practical workflow until conflict detection ships:

1. `kcmd pull` to refresh local state before editing.
2. `kcmd push --dry-run` to preview mutations.
3. On ambiguous remote edits, pull again and diff `catalog/` manually.

### EntryLink reconciliation errors

When `publishing.entryLinks` is declared, push compares local vs remote links. A failed create surfaces as:

```
Failed to create EntryLink: <message>
```

Common causes: target entry or glossary term UID in local YAML does not match a live catalog resource, or `publishing.entryLinks` includes types not listed under `snapshot.entryLinks`.

---

## OKF web crawl cap and fetch limits

The OKF enrichment agent runs a **web pass** after the BigQuery pass. Crawl policy is enforced inside the `fetch_url` tool — the LLM cannot bypass it.

### Hard limits (CLI defaults)

| Flag | Default | Enforced by |
| --- | --- | --- |
| `--web-max-pages` | `100` | Session page budget |
| `--web-max-depth` | `2` | Hop distance from seeds |
| `--web-allowed-host` | seed hosts only | Hostname allow-list |
| `--web-allowed-path-prefix` | none | Path prefix filter |
| `--web-denied-path-substring` | none | Path blocklist |

Use `--no-web` to skip the web pass entirely during iteration.

### `fetch_url` rejection reasons

When a fetch is rejected, the tool returns `{"error": "<reason>", …}` instead of page content. Do not retry the same URL.

<AccordionGroup>
<Accordion title="max_pages reached">

Budget exhausted. Stop crawling or re-run with a higher `--web-max-pages`. The web-ingestion prompt instructs the agent to stop when this error appears.

</Accordion>
<Accordion title="host not in allowed list">

URL hostname is outside seed hosts plus any `--web-allowed-host` values. Add the host explicitly if it is authoritative documentation.

</Accordion>
<Accordion title="path not in allowed prefixes / denied substring">

Path filters blocked the URL. Adjust `--web-allowed-path-prefix` or `--web-denied-path-substring`.

</Accordion>
<Accordion title="exceeds max_depth">

Link is too many hops from a seed. Raise `--web-max-depth` or choose closer seed URLs.

</Accordion>
<Accordion title="URL not reachable from a seed">

The agent invented a URL not returned as a link from a fetched page. Only follow links discovered in prior fetches.

</Accordion>
<Accordion title="fetch failed / non-HTML content-type">

Network errors wrap as `fetch failed: …`. Non-HTML responses (JSON, PDF without HTML) raise `non-HTML content-type`. Pick a different URL.

</Accordion>
</AccordionGroup>

### Page size truncation

HTML pages convert to markdown capped at **40 KiB**. Oversized pages include `[...truncated...]` in the body. This is expected for long reference pages.

### Web-pass write guardrails

During the web pass, `write_concept_doc` rejects **schema shrinkage** and **citation shrinkage** relative to the BQ pass. If the agent logs a write `error` mentioning `missing N schema field(s)` or `Citations section had N entries`, the web pass attempted to remove BQ-grounded content — refine seeds or re-run with `--concept` for a single table.

---

## Glossary column linking (enrichment agent)

Table mode with `--glossaries` maps columns to Dataplex terms and injects `links.definition` into table YAML. This path fails **silently** (with warnings) when prerequisites are missing:

| Log message | Fix |
| --- | --- |
| `[Linking] ⚠️  No glossary entries found in workspace — skipping.` | Run `kcmd pull` with glossary reference after provisioning terms |
| `[Linking] ⚠️  No glossary terms found — skipping.` | Glossary workspace has categories but no `.ref.yaml` terms |
| `[Linking] ⚠️  Schema aspect not found for <table>` | Re-run `kcmd pull` so schema aspects are present |

Required setup:

1. Initialize and pull the dataset with glossary-link manifest (`entryLinks` in snapshot/publishing/reference).
2. Pull glossary terms as reference into `catalog/glossaries/.../*.ref.yaml`.
3. Run `kcmd push` to publish new column links.

---

## Model credential failures

Knowledge Catalog tooling is **BYOC/BYOK**: you choose the model backend and supply credentials. There is no single global API key.

### OKF enrichment agent (Gemini via ADK)

Two supported paths:

<Tabs>
<Tab title="AI Studio">

```bash
export GEMINI_API_KEY=<your-key>
```

</Tab>
<Tab title="Vertex AI">

```bash
export GOOGLE_GENAI_USE_VERTEXAI=true
export GOOGLE_CLOUD_PROJECT=<id>
export GOOGLE_CLOUD_LOCATION=<region>
```

</Tab>
</Tabs>

Select the model with `--model`. Missing or invalid credentials surface as ADK/Gemini API errors at enrich time, not during `pytest` (unit tests mock network calls).

### Catalog enrichment agent (Vertex only)

`agent_runner.py` **always** sets Vertex mode from flags:

```
GOOGLE_GENAI_USE_VERTEXAI=True
GOOGLE_CLOUD_PROJECT=<--project>
GOOGLE_CLOUD_LOCATION=<--location>   # default global
```

`--project` and `--model` are **required**. Omitting them raises `UsageError` before any LLM call.

### Eval judge metrics

Dynamic and golden evaluators run deterministic metrics without auth. Judge-based metrics (`hallucination_free`, `redundancy_index`, `disambiguation_efficacy`, `absence_of_contradictions`) require:

```bash
export GOOGLE_CLOUD_PROJECT=<project>
gcloud auth application-default login
```

Without auth, the scorecard shows judge metrics as **`n/a`** with a warning. The eval CLI degrades gracefully rather than crashing. In `--run` mode, missing `trajectory.json` after an agent exit means the run did not complete — check that `kcmd` is built (`cd agents/mdcode && npm run build`) and Python deps are installed.

### GitHub MCP (optional code source)

`--repo` requires `GITHUB_PERSONAL_ACCESS_TOKEN` in the MCP server environment (default remote server or local `mcp.json`). Missing tokens cause GitHub tool calls to fail during enrichment, not at startup.

---

## Verify fixes with tests and eval

### OKF package tests

From `okf/`:

```bash
.venv/bin/pytest
```

| Test module | What it validates |
| --- | --- |
| `test_web_tools.py` | Crawl depth, path filters, unregistered URL rejection |
| `test_web_fetcher.py` | HTML-only fetch, truncation, network error wrapping |
| `test_bigquery_source.py` | BQ concept listing, view vs table sampling |
| `test_bundle_tools.py` | Web-pass schema/citation preservation |

### Catalog enrichment eval

From `agents/enrichment/`:

```bash
python -m eval --output-dir <enrichment-output-dir>
```

- **`structural_validity`** — mdcode parses; entry types match mode; overviews are clean Markdown.
- **`hallucination_free`** — requires judge auth; scores claim grounding against `trajectory.json`.
- **`entry_grounding`** (golden table mode) — no invented tables.

For end-to-end case runs:

```bash
python -m eval --run --goldens eval/goldens/thelook_ecommerce.json \
  --project <project> --runs 3
```

Prereqs: ADC, built `kcmd`, agent deps. Skipped runs log `no trajectory.json — the agent run did not complete`.

### `kcmd` scenario tests

From `agents/mdcode/`:

```bash
npm run build
npm run test
```

Scenario tests under `tests/scenarios/` cover `push_bq`, `push_kb`, `push_new_entry`, and related push/pull flows against mocked catalog APIs.

---

## Related pages

<CardGroup>
<Card title="Installation" href="/installation">
Prerequisites, Python and Node setup, and credential configuration for BigQuery, Vertex AI or Gemini, and gcloud ADC.
</Card>
<Card title="Sync catalog metadata" href="/sync-catalog-metadata">
Initialize workspaces, pull snapshots, check status, and push local edits back to Knowledge Catalog.
</Card>
<Card title="kcmd CLI reference" href="/kcmd-cli-reference">
`kcmd` commands, init flags per source type, pull/push options, and authentication via gcloud ADC.
</Card>
<Card title="OKF enrichment CLI reference" href="/okf-enrichment-cli-reference">
`enrichment-agent enrich` flags, web crawl constraints, concept scoping, and environment variables.
</Card>
<Card title="Evaluate enrichment output" href="/evaluate-enrichment-output">
Score enrichment runs with structural checks, judge metrics, and golden-based eval.
</Card>
<Card title="Publish enriched metadata" href="/publish-enriched-metadata">
Push mdcode workspaces with `kcmd` and reconcile entry links without modifying read-only reference layers.
</Card>
</CardGroup>
