tonhowtf/omniget · error

nenhum CSV no export; aponte para o zip do LinkedIn ou para…

Error message

nenhum CSV no export; aponte para o zip do LinkedIn ou para a pasta extraida

What it means

Source::open walks either the extracted directory (up to depth 4) or the zip's entries collecting CSV files, then checks whether the resulting file set is empty. If neither the zip nor the directory contains any CSVs, the export is useless to the parser and this error is returned.

Solutions

  1. Point open() at the original LinkedIn export zip rather than a hand-modified/extracted folder — the zip path is the most reliable.
  2. Verify the archive actually contains CSVs: `unzip -l export.zip | grep -i csv` or `find extracted_dir -name '*.csv'`.
  3. Re-request the full export from LinkedIn and download the complete zip (the full export can take minutes to hours to prepare).
  4. If the CSVs are nested deeper than 4 levels, flatten the directory before opening it.

Example fix

// before
Source::open("linkedin_photos.zip")?; // not a data export

// after
// check contents first
// unzip -l linkedin_export.zip | grep .csv
Source::open("/downloads/linkedin_export.zip")?;
Defensive patterns

Strategy: validation

Validate before calling

let has_csv = if path.ends_with(".zip") {
    std::process::Command::new("unzip").args(["-l", &path]).output()
        .map(|o| String::from_utf8_lossy(&o.stdout).to_lowercase().contains(".csv"))?
} else {
    walkdir::WalkDir::new(&path).into_iter().any(|e| {
        e.map(|x| x.path().extension().map_or(false, |x| x == "csv")).unwrap_or(false)
    })
};
anyhow::ensure!(has_csv, "selected archive/folder contains no CSV files");

Try / catch

match Source::open(&path) {
    Err(e) if e.to_string().contains("nenhum CSV") => {
        eprintln!("That's not a LinkedIn data export; re-download the full export zip");
    }
    r => r?,
}

Prevention

When it happens

Trigger: Opening a zip that is not a LinkedIn export (some other archive with no .csv files); opening a directory that contains only HTML/PDF parts of the export; pointing at the download page HTML file; an export requested without the CSV-producing data categories.

Common situations: User selected 'faster' LinkedIn export which may deliver fewer/differently packaged files; user extracted only part of the zip; user passed the wrong zip entirely (e.g. photos.zip); nested directories deeper than max_depth 4 hiding the CSVs.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/2b702d4a1c17c5a2. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/linkedin/source.rs:100

                    continue;
                }
                let name = e.name().to_string();
                entries.push(name.clone());
                if is_csv(&name) {
                    files.entry(key(&name)).or_insert(name);
                }
            }
            Source::Zip {
                path: p.to_path_buf(),
                files,
            }
        };
        let empty = match &source {
            Source::Dir { files } => files.is_empty(),
            Source::Zip { files, .. } => files.is_empty(),
        };
        if empty {
            return Err(anyhow!(
                "nenhum CSV no export; aponte para o zip do LinkedIn ou para a pasta extraida"
            ));
        }
        entries.sort();
        Ok(Opened { source, entries })
    }

    /// Nomes normalizados dos CSVs disponiveis.
    pub fn names(&self) -> Vec<String> {
        let mut v: Vec<String> = match self {
            Source::Dir { files } => files.keys().cloned().collect(),
            Source::Zip { files, .. } => files.keys().cloned().collect(),
        };
        v.sort();
        v
    }

    /// Le um CSV pelo nome (aceita apelidos). Texto em UTF-8 tolerante.

View on GitHub (pinned to 8600b91f42)