tonhowtf/omniget · error · anyhow::Error

escolha a pasta de destino

Error message

escolha a pasta de destino

What it means

substack::run validates Options before exporting. If opts.dest, after trimming, is an empty string there is no directory to write the archive into, so it fails fast with 'escolha a pasta de destino' (choose the destination folder).

Solutions

  1. Set opts.dest to a valid existing-or-creatable directory path before calling run
  2. In the UI, disable the export action until a destination folder is chosen
  3. Trim and validate dest in the caller (e.g. show a folder picker) before invoking run

Example fix

// before
let opts = Options { dest: "".into(), ..Default::default() };
substack::run(&opts, progress).await?;
// after
let opts = Options { dest: "/home/user/exports/substack".into(), ..Default::default() };
substack::run(&opts, progress).await?;
Defensive patterns

Strategy: validation

Validate before calling

let dest = opts.dest.trim();
if dest.is_empty() {
    anyhow::bail!("destination folder required");
}

Type guard

fn has_dest(opts: &Options) -> bool { !opts.dest.trim().is_empty() }

Prevention

When it happens

Trigger: Calling run(&opts, progress) with opts.dest set to "", whitespace-only, or simply never assigned by the caller/UI.

Common situations: Frontend did not bind the folder-picker result into the options struct; user clicked export before selecting a folder; dest field cleared programmatically.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/blogs/substack.rs:387

            "sem a sessão do Substack não dá para listar as suas assinaturas. Capture os cookies de substack.com no gerenciador, ou digite as publicações à mão"
        ));
    }
    let v = fetcher
        .get_json("https://substack.com/api/v1/subscriptions")
        .await?;
    let subs = parse_subscriptions(&v);
    if subs.is_empty() {
        return Err(anyhow!(
            "a conta logada não tem nenhuma assinatura ativa (ou a sessão expirou)"
        ));
    }
    Ok(subs)
}

pub async fn run(opts: &Options, progress: ProgressFn) -> Result<ArchiveResult> {
    let dest = opts.dest.trim();
    if dest.is_empty() {
        return Err(anyhow!("escolha a pasta de destino"));
    }
    if !opts.markdown && !opts.html && !opts.json {
        return Err(anyhow!("escolha ao menos um formato"));
    }
    let root = PathBuf::from(dest);
    std::fs::create_dir_all(&root)?;

    let domains: Vec<String> = COOKIE_DOMAINS.iter().map(|d| d.to_string()).collect();
    let fetcher = Fetcher::new(opts.delay_ms, opts.session_netscape.as_deref(), &domains)?;

    // Lista de publicações: o que o usuário digitou tem precedência; vazio
    // significa "as minhas assinaturas".
    let targets: Vec<Subscription> = if opts.publications.is_empty() {
        crate::core::tools::report(
            &progress,
            ID,
            "discover",
            0,

View on GitHub (pinned to 8600b91f42)