unclecode/crawl4ai · info · Error
Request failed
Error message
Request failed
What it means
ArtifactNotFound raised as the fall-through when the id is well-formed but no file with any known extension exists for it (or every candidate hit FileNotFoundError). This closes the loop of the opaque-not-found design: valid-but-unknown ids, expired ids, and malformed ids all surface identically.
Source
Thrown at deploy/docker/static/playground/index.html:754
let response, responseData;
const useStreamOverride = (endpoint === 'crawl') && shouldUseStream(payload);
if (endpoint === 'llm') {
// Special handling for LLM endpoint which uses URL pattern: /llm/{encoded_url}?q={query}
const url = urls[0];
const encodedUrl = encodeURIComponent(url);
// Get the question from the LLM-specific input
const question = document.getElementById('llm-question').value.trim() || "What is this page about?";
response = await authFetch(`${api}/${encodedUrl}?q=${encodeURIComponent(question)}`, {
method: 'GET',
headers: { 'Accept': 'application/json' }
});
responseData = await response.json();
const time = Math.round(performance.now() - startTime);
if (!response.ok) {
updateStatus('error', time);
throw new Error(responseData.error || 'Request failed');
}
updateStatus('success', time);
document.querySelector('#response-content code').textContent = JSON.stringify(responseData, null, 2);
document.querySelector('#response-content code').className = 'json hljs';
forceHighlightElement(document.querySelector('#response-content code'));
} else if (endpoint === 'crawl_stream' || useStreamOverride) {
// Stream processing - now handled directly by /crawl endpoint
response = await authFetch(api, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
const reader = response.body.getReader();
let text = '';
let maxMemory = 0;
while (true) {View on GitHub (pinned to 7e80152142)
Solutions
- Re-run the crawl to regenerate the artifact — a well-formed but unknown id cannot be recovered
- Persist the crawl output (or the artifact bytes) in your own storage at generation time if it must survive
- Mount a persistent volume for the artifact dir if container restarts are wiping the store
Defensive patterns
Strategy: try-catch
Type guard
def is_valid_artifact_id(a):
return isinstance(a, str) and len(a) == 32 and all(c in "0123456789abcdef" for c in a) Try / catch
try:
path, mime = resolve_artifact(artifact_id)
except ArtifactNotFound:
log.info("artifact %s unknown/expired; regenerating", artifact_id)
return await regenerate(...) # only recovery path Prevention
- Persist artifact bytes or crawl outputs at generation time
- Use persistent volumes for the artifact dir across container restarts
- Don't cache artifact ids beyond their TTL
When it happens
Trigger: GETing /artifact/{valid-hex-id} for an id that was never issued (fabricated), was already expired-and-reaped, or whose underlying file was deleted — the loop over _KIND extensions completes without a match.
Common situations: Random/forged ids probing the API; artifacts aged out between listing and fetch; store directory wiped/recreated (container recreation without a persistent volume).
Related errors
- Timeout after {timeout}ms waiting for selector '{wait_for}'
- Invalid wait_for parameter: '{wait_for}'. It should be eithe
- Invalid config
- 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/ab90697b6df7bd0c.
Report an issue: GitHub.