{"record":{"id":"796a1c96a38ddd67","repo":"tonhowtf/omniget","slug":"o-goodreads-recusou-o-pedido-de-export-http-ele-s-deixa","errorCode":null,"errorMessage":"o Goodreads recusou o pedido de export (HTTP {}). Ele só deixa gerar um a cada poucos dias","messagePattern":"o Goodreads recusou o pedido de export \\(HTTP (.+?)\\)\\. Ele só deixa gerar um a cada poucos dias","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/lists/goodreads.rs","lineNumber":286,"sourceCode":"        f.pace().await;\n        let resp = f\n            .client()\n            .post(export_post_url(&uid))\n            .header(reqwest::header::REFERER, IMPORT_URL)\n            .header(reqwest::header::ORIGIN, \"https://www.goodreads.com\")\n            .header(reqwest::header::ACCEPT, \"*/*\")\n            .header(\"X-Requested-With\", \"XMLHttpRequest\")\n            .header(\"X-CSRF-Token\", token)\n            .header(\n                reqwest::header::CONTENT_TYPE,\n                \"application/x-www-form-urlencoded\",\n            )\n            .body(\"format=json\")\n            .send()\n            .await?;\n        let status = resp.status();\n        if !status.is_success() && status.as_u16() != 302 {\n            return Err(anyhow!(\n                \"o Goodreads recusou o pedido de export (HTTP {}). Ele só deixa gerar um a cada poucos dias\",\n                status\n            ));\n        }\n    }\n\n    // Espera: o CSV é gerado em segundo plano e responde 404 até ficar pronto.\n    let limit = Duration::from_secs(opts.wait_secs.clamp(30, 3600));\n    loop {\n        let code = f.head_status(&csv_url).await.unwrap_or(0);\n        if code == 200 {\n            break;\n        }\n        if code != 404 && code != 0 && code != 403 {\n            return Err(anyhow!(\n                \"o Goodreads respondeu HTTP {} no arquivo do export\",\n                code\n            ));","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/lists/goodreads.rs#L268-L304","documentation":"After POSTing to /review_porter/export/<id>, trigger_and_wait accepts success (2xx) or a 302 redirect; any other non-success status means Goodreads refused the export request. Since Goodreads rate-limits export generation to once every few days, the error message explicitly calls out that restriction.","triggerScenarios":"The export-trigger POST returns e.g. 403/429/500: requesting an export sooner than Goodreads' cooldown allows, an invalid/expired CSRF token, or a rate-limited/blocked session.","commonSituations":"User (or this tool) already generated an export within the last few days and force=true was set; CSRF token mismatch from stale cookies; aggressive retry loop tripping Goodreads rate limiting.","solutions":["Don't force a new export: rerun with force=false so the existing ready export link is reused instead of POSTing again.","Wait a few days for Goodreads' export cooldown to lapse before forcing a new export.","Recapture cookies (a stale CSRF token can cause rejection) and retry once.","If HTTP 429, back off significantly — repeated attempts prolong any rate-limit block."],"exampleFix":"// before\nrun(&f, &Options { force: true, .. }).await?; // rejected, export already made this week\n\n// after\nrun(&f, &Options { force: false, .. }).await?; // reuse existing export link","handlingStrategy":"retry","validationCode":"// don't attempt a forced export if a ready one exists\nlet page = fetcher.get_text(IMPORT_URL).await?;\nlet opts = if export_link(&page).is_some() {\n    Options { force: false, ..opts }\n} else { opts };","typeGuard":null,"tryCatchPattern":"match run(&fetcher, &opts).await {\n    Err(e) if e.to_string().contains(\"recusou o pedido de export\") => {\n        eprintln!(\"Export cooldown active; rerun later with force=false\");\n    }\n    r => r?,\n}","preventionTips":["Only force a new export every few days at most","Respect HTTP 429 with long backoff","Recapture cookies if rejection persists (stale CSRF token)"],"tags":["http","rate-limit","goodreads","api"],"backgroundTag":"http-error-response","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"}