How to Update Metadata Entries via the Snapshot Module in Google Knowledge Catalog

The CatalogSnapshot.updateEntry() method executes a deterministic three-phase workflow—loading the existing entry, validating and mutating specified fields against registered aspects, and persisting changes via the local layout—to safely modify Dataplex metadata while enforcing service constraints.

The GoogleCloudPlatform/knowledge-catalog repository provides a local representation of Dataplex catalogs through its snapshot module. When updating metadata entries via the snapshot module, the system guarantees consistency by validating every change against the manifest aspect types and entry group source definitions before writing to disk.

The updateEntry Workflow Execution Path

The core logic resides in toolbox/mdcode/src/libts/snapshot.ts. When you invoke CatalogSnapshot.updateEntry(entry, fields), the engine executes the following deterministic path:

Phase 1: Loading the Existing Entry

The workflow begins by retrieving the current state from the local catalog layout. The snapshot calls this._layout.loadEntry(entry.name) (implemented in toolbox/mdcode/src/libts/layout.ts) to fetch the existing entry object. This ensures all subsequent mutations apply as updates to the authoritative local copy rather than creating orphan records.

Phase 2: Field Validation and Mutation

The method iterates over the fields array you provided, applying distinct logic based on the field name:

Resource Field Handling If the field equals "resource", the function copies the description (and any other explicitly supported resource fields) from the supplied entry.resource into the existing entry’s resource object. Resource-level updates are intentionally limited to prevent corruption of system-managed identifiers.

Aspect Field Handling For all other strings in the fields array, the snapshot interprets the value as an aspect key (formatted as project.location.type):

  1. Type Resolution: The aspect key resolves to a full type name via dataplex._typeRefToName (defined in toolbox/mdcode/src/libts/gcp/dataplex.ts).
  2. Registration Check: The snapshot validates the aspect is registered in the local manifest by checking this._aspectTypes.has(). Unregistered aspects trigger an immediate error.
  3. Ingestion Guard: If the catalog is marked as ingested (manifest.source.ingestedEntries), the code inspects the entry-type’s requiredAspects. Attempting to modify a required aspect (managed by Dataplex) results in an error, as these are immutable service properties.
  4. Mutation: Valid user-managed aspects are either added/updated (existingEntry.aspects[f] = entry.aspects[f]) or removed (delete existingEntry.aspects[f]) depending on whether the supplied entry contains data for that aspect key.

Phase 3: Persisting Changes to Disk

After successful mutation, the snapshot commits the changes through this._layout.saveEntry(entry.name, existingEntry). This writes the modified entry back to the local catalog path, ensuring the on-disk representation stays synchronized with your in-memory changes.

Validation Constraints and Business Rules

The snapshot module enforces strict guardrails to maintain catalog integrity:

User-Managed Entry Groups Only

Creation, deletion, and certain updates are prohibited when manifest.source.ingestedEntries is true. This constraint ensures you cannot accidentally overwrite metadata that Dataplex automatically harvests from source systems.

Aspect Registration Requirements

Only aspects listed in snapshotConfig.aspects or required by the entry type definition are accepted. The CatalogSnapshot validates every aspect against this._aspectTypes.has() before mutation, preventing schema drift in the local catalog.

Resource Field Limitations

Currently, the snapshot only handles the description field within the resource object. Attempting to modify other resource properties (like system-generated IDs or creation timestamps) has no effect and may be silently ignored or rejected depending on the implementation version.

Practical Implementation Examples

The following patterns demonstrate updating an entry's description and a custom aspect in both TypeScript and Python:

// TypeScript implementation from toolbox/mdcode/src/libts/snapshot.ts
const snapshot = await CatalogSnapshot.fromPath('/path/to/catalog', ctx);

// Retrieve the current entry
const entry = await snapshot.lookupEntry('my_dataset');

// Modify the description and a custom aspect
entry.resource = { description: 'New description' };
entry.aspects = {
  'myproject.location.mycustomaspect': { foo: 'bar' }
};

// Apply changes – the fields array specifies which parts to touch
await snapshot.updateEntry(entry, ['resource', 'myproject.location.mycustomaspect']);

# Python equivalent from samples/enrichment

from enrichment.metadata.snapshot import CatalogSnapshot

snapshot = CatalogSnapshot.from_path('/path/to/catalog', ctx)

entry = snapshot.lookup_entry('my_dataset')
entry.resource.description = 'New description'
entry.aspects['myproject.location.mycustomaspect'] = {'foo': 'bar'}

snapshot.update_entry(entry, ['resource', 'myproject.location.mycustomaspect'])

Summary

  • The updateEntry() method in toolbox/mdcode/src/libts/snapshot.ts implements a three-phase workflow: load via Layout.loadEntry(), validate and mutate fields, then save via Layout.saveEntry().
  • Aspect validation requires every modified aspect to be registered in this._aspectTypes and not listed as a required aspect for ingested catalogs.
  • Resource updates are restricted to the description field; other resource properties remain immutable through this API.
  • Ingested entry protection prevents modifications to automatically managed metadata when manifest.source.ingestedEntries is enabled.
  • Changes are persisted atomically to the local catalog path, maintaining synchronization with the Dataplex service definitions.

Frequently Asked Questions

What happens if I attempt to update an unregistered aspect?

The snapshot throws a validation error. Before applying any mutation, the code checks this._aspectTypes.has() to verify the aspect is defined in the snapshot configuration. This prevents catalog corruption from typos or schema mismatches.

Can I modify metadata for automatically ingested entries?

No. When manifest.source.ingestedEntries is true, the system blocks creation, deletion, and modification of required aspects. These entries are treated as read-only mirrors of the external Dataplex state to prevent synchronization conflicts.

How does the snapshot distinguish between resource updates and aspect updates?

The method checks the string value in the fields array. If the value equals "resource", it copies specific allowed fields (currently only description) from entry.resource. All other strings are interpreted as aspect keys that undergo full type resolution and registration validation before mutation.

Where are the changes physically stored after calling updateEntry()?

The Layout class in toolbox/mdcode/src/libts/layout.ts handles persistence. The saveEntry() method writes the modified entry structure back to the local catalog path provided during CatalogSnapshot.fromPath() initialization, ensuring durable storage of your metadata changes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →