{"record":{"id":"3c1bf6635e5fd27c","repo":"tonhowtf/omniget","slug":"jpeg-sem-cabecalho-sof","errorCode":null,"errorMessage":"JPEG sem cabecalho SOF","messagePattern":"JPEG sem cabecalho SOF","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/jpeg_pdf.rs","lineNumber":48,"sourceCode":"        if (0xD0..=0xD9).contains(&marker) || marker == 0x01 {\n            i += 2;\n            continue;\n        }\n        let len = u16::from_be_bytes([data[i + 2], data[i + 3]]) as usize;\n        let is_sof = matches!(marker, 0xC0..=0xCF) && !matches!(marker, 0xC4 | 0xC8 | 0xCC);\n        if is_sof {\n            let height = u16::from_be_bytes([data[i + 5], data[i + 6]]) as u32;\n            let width = u16::from_be_bytes([data[i + 7], data[i + 8]]) as u32;\n            let components = data[i + 9];\n            return Ok(JpegInfo {\n                width,\n                height,\n                components,\n            });\n        }\n        i += 2 + len;\n    }\n    Err(anyhow!(\"JPEG sem cabecalho SOF\"))\n}\n\npub fn is_jpeg(data: &[u8]) -> bool {\n    data.len() > 3 && data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF\n}\n\n/// Monta o PDF em memória. Página no tamanho da imagem em pontos (72 dpi).\npub fn build_pdf(images: &[Vec<u8>]) -> anyhow::Result<Vec<u8>> {\n    if images.is_empty() {\n        return Err(anyhow!(\"nenhuma imagem\"));\n    }\n    let mut out: Vec<u8> = Vec::new();\n    let mut offsets: Vec<usize> = Vec::new();\n    out.extend_from_slice(b\"%PDF-1.4\\n%\\xE2\\xE3\\xCF\\xD3\\n\");\n\n    // objetos: 1 catalog, 2 pages, depois por imagem: page, xobject, content\n    let n_pages = images.len();\n    let obj_page = |i: usize| 3 + i * 3;","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/jpeg_pdf.rs#L30-L66","documentation":"After confirming the SOI marker, jpeg_info walks the segment chain looking for a Start-Of-Frame marker (SOF0/SOF2, etc.) that carries width/height/channels. If it consumes the whole buffer without finding one, it raises \"JPEG sem cabecalho SOF\" (JPEG without SOF header). This happens for valid-signature but structurally broken or exotic files.","triggerScenarios":"Truncated JPEG cut off before the SOF segment; progressive/EXIF files whose scan data precedes parsing assumptions and the loop skips past the SOF; concatenated/corrupted buffers where segment lengths lead parsing astray.","commonSituations":"Partially downloaded image (only header bytes); file corrupted in transfer/storage; JPEG produced by an unusual encoder that this simple parser does not handle.","solutions":["Verify the file opens in an image viewer / `file` reports a complete JPEG — if not, re-download it","Compare bytes received against Content-Length to detect truncation before parsing","Fall back to a robust decoder (image crate) to extract dimensions when the custom parser fails"],"exampleFix":"// before\nlet info = jpeg_info(&bytes)?; // Err: JPEG sem cabecalho SOF\n// after\nlet info = match jpeg_info(&bytes) {\n    Ok(i) => i,\n    Err(_) => {\n        let img = image::load_from_memory(&bytes)?; // robust fallback\n        JpegInfo { width: img.width(), height: img.height(), components: 3 }\n    }\n};","handlingStrategy":"fallback","validationCode":"// ensure the whole file arrived before parsing\nassert_eq!(bytes.len(), expected_content_length as usize, \"JPEG truncado\");","typeGuard":null,"tryCatchPattern":"let info = jpeg_info(&bytes).or_else(|_| {\n    image::load_from_memory(&bytes).map(|img| JpegInfo {\n        width: img.width(), height: img.height(), components: 3,\n    })\n})?;","preventionTips":["Validate downloads completed (Content-Length match) before parsing","Fall back to a full image decoder when the lightweight SOF walker fails","Reject zero-length or suspiciously small files early"],"tags":["jpeg","image","corrupt-file","rust"],"backgroundTag":"unexpected-response-shape","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}