spacedriveapp/spacedrive · error
Entry has no content_id
Error message
Entry has no content_id
What it means
The OCR processor requires entry.content_id because extracted text is written into the content_identity row. process() unwraps the Option and errors when None: the entry passed the mime-type check but was never identified (no content identity created), so there is nowhere to store OCR output.
Source
Thrown at core/src/ops/media/ocr/processor.rs:75
}
if entry.content_id.is_none() {
return false;
}
entry.mime_type.as_ref().map_or(false, |m| {
super::is_ocr_supported(m, self.library.core_context().file_type_registry())
})
}
pub async fn process(
&self,
db: &sea_orm::DatabaseConnection,
entry: &ProcessorEntry,
) -> Result<ProcessorResult> {
let content_id = entry
.content_id
.ok_or_else(|| anyhow::anyhow!("Entry has no content_id"))?;
debug!("→ Extracting text via OCR for: {}", entry.path.display());
// Extract text
let extracted_text = super::extract_text_from_file(&entry.path, &self.languages).await?;
if extracted_text.is_empty() {
debug!("No text extracted from: {}", entry.path.display());
return Ok(ProcessorResult::success(0, 0));
}
debug!("✓ Extracted {} characters of text", extracted_text.len());
// Update content_identity with extracted text
use crate::infra::db::entities::content_identity;
let ci = content_identity::Entity::find_by_id(content_id)
.one(db)View on GitHub (pinned to 6dfeccf211)
Solutions
- Ensure the identifier processor runs before OCR in the pipeline ordering
- Add a content_id requirement to the processor's wants_to_process check so unqualified entries are filtered, not errored
- Re-run identification on affected entries, then re-queue OCR
Example fix
// before (wants_to_process)
entry.mime_type.as_ref().map_or(false, |m| {
super::is_ocr_supported(m, self.library.core_context().file_type_registry())
})
// after: also require a content identity, mirroring process()'s hard requirement
entry.mime_type.as_ref().map_or(false, |m| {
super::is_ocr_supported(m, self.library.core_context().file_type_registry())
}) && entry.content_id.is_some() Defensive patterns
Strategy: type-guard
Validate before calling
// Only enqueue OCR when a content identity exists
if entry.content_id.is_some() {
ocr_processor.enqueue(entry).await?;
} Type guard
fn is_ocr_eligible(entry: &ProcessorEntry, registry: &FileTypeRegistry) -> bool {
entry.content_id.is_some()
&& entry
.mime_type
.as_ref()
.map_or(false, |m| super::is_ocr_supported(m, registry))
} Try / catch
match ocr.process(db, &entry).await {
Ok(res) => { /* aggregate results */ }
Err(e) if e.to_string().contains("Entry has no content_id") => {
tracing::debug!(path = %entry.path.display(), "skipping OCR: entry not yet identified");
}
Err(e) => return Err(e),
} Prevention
- Keep identification ahead of OCR in processor pipeline ordering
- Mirror every hard requirement of process() in wants_to_process filters
- Re-queue skipped entries after identification completes
When it happens
Trigger: Running the OCR processor on entries the identifier has not processed yet (pipeline ordering wrong); entries whose identification failed or was skipped; manually enqueuing entries into the processor without the identify step.
Common situations: Processor registry ordering changed so OCR runs before identification; a new file picked up mid-write before identify completed; identification errors silently skipped an entry.
Related errors
- ContentIdentity not found
- ContentIdentity not found
- Entry not found
- ContentIdentity missing UUID
- Proxy generation failed: {}
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/6be7474e19f76ab7.
Report an issue: GitHub.