{"record":{"id":"d3523744eeb958e6","repo":"tonhowtf/omniget","slug":"a-chave-local-do-sponsorblock-est-corrompida","errorCode":null,"errorMessage":"a chave local do SponsorBlock está corrompida","messagePattern":"a chave local do SponsorBlock está corrompida","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/sponsorblock.rs","lineNumber":271,"sourceCode":"        if par[1].start < par[0].end {\n            return Err(anyhow!(\"dois trechos se sobrepõem em {:.1}s\", par[1].start));\n        }\n    }\n    Ok(())\n}\n\n/// O corpo exato do `POST /api/skipSegments`.\npub fn build_payload(\n    video_id: &str,\n    user_id: &str,\n    duration: f64,\n    segments: &[NewSegment],\n) -> anyhow::Result<serde_json::Value> {\n    if video_id.len() != 11 {\n        return Err(anyhow!(\"não reconheci o vídeo do YouTube\"));\n    }\n    if user_id.trim().len() < 30 {\n        return Err(anyhow!(\"a chave local do SponsorBlock está corrompida\"));\n    }\n    validate_segments(segments, duration)?;\n    let segs: Vec<serde_json::Value> = segments\n        .iter()\n        .map(|s| {\n            let mut o = serde_json::json!({\n                \"segment\": [s.start, s.end],\n                \"category\": s.category,\n                \"actionType\": s.action_type,\n            });\n            if !s.description.trim().is_empty() {\n                o[\"description\"] = serde_json::Value::String(s.description.trim().to_string());\n            }\n            o\n        })\n        .collect();\n    let mut body = serde_json::json!({\n        \"videoID\": video_id,","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/sponsorblock.rs#L253-L289","documentation":"build_payload requires the local SponsorBlock user ID (the privateID stored locally) to be at least 30 characters after trimming. This acts as a sanity check that the stored credentials file is intact: a truncated or empty key would silently submit garbage or fail server-side, so the library refuses up front.","triggerScenarios":"Calling build_payload (or submit, which calls local_user_id()) when the stored SponsorBlock key is missing, empty, whitespace, or truncated to fewer than 30 characters.","commonSituations":"First run before the key was ever generated/saved; config file corrupted or partially written; the key copied with the tail cut off; config directory permissions or sync tools truncating the file.","solutions":["Regenerate/obtain the SponsorBlock private ID and re-save it, then retry.","Inspect the stored key file: check it is >= 30 chars with no truncation or stray whitespace.","Ensure the code path that creates the key actually ran before submit is called (no partial first-run setup).","Verify the config directory is writable and not being clobbered by file sync/backup tools."],"exampleFix":"// before\nlet user = config.get(\"sponsorblock_key\").unwrap_or_default(); // \"\"\n// after\nlet user = local_user_id()?; // loads or creates a valid 30+ char private ID","handlingStrategy":"validation","validationCode":"fn has_valid_user_id(user: &str) -> bool {\n    user.trim().len() >= 30\n}","typeGuard":"fn valid_credentials(user: &str) -> Option<&str> {\n    (user.trim().len() >= 30).then_some(user)\n}","tryCatchPattern":"match build_payload(&id, &user, dur, &segs) {\n    Err(e) if e.to_string().contains(\"chave local\") => regenerate_and_store_key().await?,\n    other => other?,\n}","preventionTips":["Call local_user_id() (which creates the key if needed) before submitting instead of reading raw config.","Check key length at startup and prompt re-setup if invalid.","Protect the config file from truncation by sync/backup tools."],"tags":["sponsorblock","credentials","rust","config"],"backgroundTag":"missing-credentials","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}