tonhowtf/omniget · error
não achei o token anti-CSRF do Goodreads; recapture os…
Error message
não achei o token anti-CSRF do Goodreads; recapture os cookies e tente de novo
What it means
When no ready export link exists on the page (or opts.force is set), trigger_and_wait must POST to /review_porter/export/<id>, which requires the anti-CSRF token embedded in the import page. If csrf_token() fails to extract it, the export cannot be triggered and this error is returned, advising a cookie recapture.
Solutions
- Recapture goodreads.com cookies with the extension while logged in, then rerun.
- Retry shortly after — if Goodreads served an A/B or degraded page once, a fresh fetch usually includes the token.
- If persistent, update the csrf_token() extraction pattern to match Goodreads' current markup (check the import page's HTML for the token input/meta).
- Skip the forced export if a ready export link exists (run without force) — the ready path does not need the CSRF token.
Example fix
// before
let opts = Options { force: true, .. };
run(&fetcher, &opts).await?; // csrf token missing
// after: reuse existing export when possible
let opts = Options { force: false, .. };
run(&fetcher, &opts).await?; Defensive patterns
Strategy: fallback
Validate before calling
let page = fetcher.get_text(IMPORT_URL).await?;
if csrf_token(&page).is_none() && export_link(&page).is_none() {
prompt_cookie_recapture(); // neither a token nor an existing export is usable
} Try / catch
match run(&fetcher, &opts).await {
Err(e) if e.to_string().contains("anti-CSRF") => {
// fall back to reusing existing export instead of forcing a new one
run(&fetcher, &Options { force: false, ..opts }).await?;
}
r => r?,
} Prevention
- Avoid force=true unless an export is genuinely stale
- Recapture cookies when the token extraction fails
- Prefer the ready-export path whenever a link exists on the page
When it happens
Trigger: csrf_token() returning None on the fetched page: the token's markup attribute changed, the page variant served doesn't include the token, or the session is semi-valid (signed in but page rendered without form token).
Common situations: Goodreads rotating or renaming the CSRF input/meta element; stale cookies producing a degraded page; locale-specific page variants omitting the token field; forced re-export on a page variant that omits the form.
Related errors
- nenhum favorito foi lido: esses perfis costumam exigir a…
- nenhum like foi lido: os likes só aparecem com a sessão do…
- o X serviu a versao deslogada da pagina
- a sessão do Goodreads não está válida: capture os cookies…
- não achei o id da sua conta na página de importação do…
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/ad902273c393d977.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/tools/lists/goodreads.rs:264
async fn trigger_and_wait(f: &Fetcher, opts: &Options, p: &ProgressFn) -> Result<(String, u64)> {
let page = f.get_text(IMPORT_URL).await?;
if is_signed_out(&page) {
return Err(anyhow!(
"a sessão do Goodreads não está válida: capture os cookies de goodreads.com na extensão"
));
}
let uid = user_id(&page).ok_or_else(|| {
anyhow!("não achei o id da sua conta na página de importação do Goodreads")
})?;
let csv_url = export_csv_url(&uid);
// Se já existe um export pronto, aproveita: o Goodreads só deixa gerar um
// a cada poucos dias, e gerar um novo apaga o anterior.
let ready = !opts.force && export_link(&page).is_some();
let started = Instant::now();
if !ready {
let token = csrf_token(&page).ok_or_else(|| {
anyhow!(
"não achei o token anti-CSRF do Goodreads; recapture os cookies e tente de novo"
)
})?;
f.pace().await;
let resp = f
.client()
.post(export_post_url(&uid))
.header(reqwest::header::REFERER, IMPORT_URL)
.header(reqwest::header::ORIGIN, "https://www.goodreads.com")
.header(reqwest::header::ACCEPT, "*/*")
.header("X-Requested-With", "XMLHttpRequest")
.header("X-CSRF-Token", token)
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.body("format=json")
.send()View on GitHub (pinned to 8600b91f42)