← Files Microsoft DataverseARCHIVED FILE
skills/dv-metadata/references/metadata-propagation.md
2.27 KB · Oct 2, 2026 · 00:29 UTC
# Metadata Propagation Delays and Lock Contention
After creating tables, columns, or alternate keys, Dataverse runs internal metadata operations (index building, cache propagation) that can take 3-30 seconds. Submitting another metadata operation while these are still running causes lock contention errors ("another operation is running").
**Common symptoms:**
- Picklist columns fail with `0x80040216` immediately after table creation
- Lookup `@odata.bind` operations fail with "Invalid property" shortly after column creation
- `update_table` (MCP) fails with "EntityId not found in MetadataCache"
- Alternate key creation fails with lock contention after table creation
- Lookup creation fails with "another customization operation is running"
**Mitigation — use phased creation, not interleaved:**
When creating many tables with alternate keys and lookups (e.g., multi-table import schema), create them in phases rather than interleaving operations on the same table:
1. **Phase 1: Create ALL tables** (5-8s delay between each)
2. **Wait 15-30s** for metadata propagation
3. **Phase 2: Create ALL alternate keys** (3s delay between each)
4. **Wait 15-30s** for index building
5. **Phase 3: Create ALL lookups** (3s delay between each)
Do NOT interleave: `create table A → create key A → create table B → create key B`. This causes lock contention because key A's index build blocks table B's creation.
**Retry pattern:** Wrap metadata operations with retry for transient lock errors. Use check-first helpers (`ensure_table`, `ensure_alternate_key`) to handle "already exists" before calling this — the retry wrapper only handles lock contention:
```python
import time
def retry_metadata(fn, description, max_attempts=5):
for attempt in range(max_attempts):
try:
return fn()
except Exception as e:
err = str(e)
if "another" in err.lower() and "running" in err.lower():
wait = 10 * (attempt + 1)
print(f" {description}: lock contention, waiting {wait}s (attempt {attempt+1}/{max_attempts})...")
time.sleep(wait)
continue
raise
print(f" WARNING: {description} failed after {max_attempts} attempts")
return None
```
SHA-256: 6480224b15a192152e6437d80f6e26d942f7ad1d4093ca498dc3f847f096108f