unclecode/crawl4ai · info · Error
Invalid config
Error message
Invalid config
What it means
ArtifactNotFound raised when the artifact file exists and is regular but its mtime is older than ARTIFACT_TTL_SECONDS (default 3600 s). The file is unlinked (best-effort) and the lookup fails — artifacts are short-lived by design, and expiry is hidden behind the same not-found error.
Source
Thrown at deploy/docker/static/playground/index.html:580
async function pyConfigToJson() {
const code = cm.getValue().trim();
if (!code) return {};
// Server requires `type` alongside `code` (CrawlerRunConfig | BrowserConfig).
// The UI already tracks this in #cfg-type; omitting it always 400s Advanced Config.
const cfgType = document.getElementById('cfg-type').value;
const res = await authFetch('/config/dump', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ type: cfgType, code }),
});
const statusEl = document.getElementById('cfg-status');
if (!res.ok) {
const msg = await res.text();
statusEl.textContent = '✖ config error';
statusEl.className = 'text-xs text-red-400';
throw new Error(msg || 'Invalid config');
}
statusEl.textContent = '✓ parsed';
statusEl.className = 'text-xs text-green-400';
return await res.json();
}
// ================ SERVER COMMUNICATION ================
// Update status UI
function updateStatus(status, time, memory, peakMemory) {
const statusEl = document.getElementById('execution-status');
const badgeEl = document.querySelector('#status-badge span:first-child');
const textEl = document.querySelector('#status-badge span:last-child');
statusEl.classList.remove('hidden');
badgeEl.className = 'w-3 h-3 rounded-full mr-2';View on GitHub (pinned to 7e80152142)
Solutions
- Retrieve artifacts promptly — within CRAWL4AI_ARTIFACT_TTL_SECONDS of creation
- Persist important artifacts to your own storage immediately after the crawl response arrives
- Raise CRAWL4AI_ARTIFACT_TTL_SECONDS on the server if longer retrieval windows are required
Example fix
# after crawl, download the artifact immediately instead of caching the id
meta = write_artifact("screenshot", data)
# fetch /artifact/{meta['artifact_id']} now, or store `data` yourself Defensive patterns
Strategy: retry
Validate before calling
import time
TTL = int(os.environ.get("CRAWL4AI_ARTIFACT_TTL_SECONDS", 3600))
def artifact_likely_alive(meta, now=None) -> bool:
return (now or time.time()) - meta["created_at"] < TTL - 60 # 1 min slack Try / catch
try:
path, mime = resolve_artifact(meta["artifact_id"])
except ArtifactNotFound:
meta = await regenerate_artifact(...) # expired -> re-crawl and re-store
path, mime = resolve_artifact(meta["artifact_id"]) Prevention
- Download artifacts immediately after the crawl response
- Copy important artifacts to your own durable storage
- Size your retrieval pipeline latency against CRAWL4AI_ARTIFACT_TTL_SECONDS
When it happens
Trigger: Fetching /artifact/{id} more than an hour (or configured TTL) after it was written; a pause between crawl and retrieval longer than the TTL; low TTL deployments.
Common situations: Retrying a downstream pipeline hours later; queuing artifact downloads behind slow workers; crawls run at night with retrieval the next morning.
Related errors
- Timeout after {timeout}ms waiting for selector '{wait_for}'
- Invalid wait_for parameter: '{wait_for}'. It should be eithe
- Request failed
- Timeout after {timeout}ms waiting for selector '{css_selecto
- Invalid CSS selector: '{css_selector}'
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/0ffb3a336aeaac24.
Report an issue: GitHub.