{"record":{"id":"1d644979966489d2","repo":"tauri-apps/tauri","slug":"failed-to-convert-base64-to-string","errorCode":null,"errorMessage":"failed to convert base64 to string","messagePattern":"failed to convert base64 to string","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tauri-macos-sign/src/lib.rs","lineNumber":339,"sourceCode":"          self\n            .arg(\"--key-id\")\n            .arg(key_id)\n            .arg(\"--key\")\n            .arg(key_path)\n            .arg(\"--issuer\")\n            .arg(issuer),\n        )\n      }\n    }\n  }\n}\n\nfn decode_base64(base64_input: &OsStr, out_path: &Path) -> Result<()> {\n  use base64::Engine;\n\n  let input = base64_input\n    .to_str()\n    .expect(\"failed to convert base64 to string\");\n\n  // strip whitespace before decoding\n  let cleaned: String = input.chars().filter(|c| !c.is_ascii_whitespace()).collect();\n\n  let decoded = base64::engine::general_purpose::STANDARD\n    .decode(&cleaned)\n    .map_err(Error::Base64Decode)?;\n\n  std::fs::write(out_path, &decoded).map_err(|error| Error::Fs {\n    context: \"failed to write decoded certificate\",\n    path: out_path.to_path_buf(),\n    error,\n  })?;\n\n  Ok(())\n}\n\nfn assert_command(","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/tauri-apps/tauri/blob/52e4b6e71d8632a7e648f866c442e287ecddee34/crates/tauri-macos-sign/src/lib.rs#L321-L357","documentation":"Panic in tauri-macos-sign's decode_base64 (used for Keychain::with_certificate and provisioning profiles): the base64-encoded certificate/profile arrives as an OsStr (typically from the APPLE_CERTIFICATE / APPLE_PROVISIONING_PROFILE inputs of the macOS signing flow) and .to_str().expect(\"failed to convert base64 to string\") fails when the value contains non-UTF-8 bytes — before any base64 decoding happens.","triggerScenarios":"Supplying the certificate or provisioning profile secret from an OsString source with invalid UTF-8: a CI secret written by a binary process, a .env file saved with a legacy encoding or BOM, or a filename/argument with mangled bytes.","commonSituations":"Locally-sourced env vars from shells with legacy encodings; secrets piped through tools that inject a BOM or stray bytes; provisioning profiles renamed with invalid byte sequences.","solutions":["Regenerate the base64 cleanly: `openssl base64 -in cert.p12 -out cert.b64` and re-store the secret","Verify the storage is UTF-8: `iconv -f utf-8 -t utf-8 .env > /dev/null` and fix any reported bytes","In your own wrapper, read the secret with std::env::var (which rejects invalid UTF-8 with a clear error) instead of var_os"],"exampleFix":"# before: .env saved as Latin-1 with stray bytes → panic\n\n# after\nopenssl base64 -in Certificates.p12 -A -out cert.b64\nexport APPLE_CERTIFICATE=\"$(cat cert.b64)\"  # verified UTF-8","handlingStrategy":"validation","validationCode":"// std::env::var fails with a clear error on non-UTF-8 instead of panicking deep in the signer\nlet cert = std::env::var(\"APPLE_CERTIFICATE\")\n    .map_err(|_| \"APPLE_CERTIFICATE missing or not valid UTF-8\")?;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store APPLE_CERTIFICATE / APPLE_PROVISIONING_PROFILE as UTF-8 text generated via openssl base64","Verify secret files with iconv before CI consumes them","Avoid writing env values from binary processes"],"tags":["macos","signing","base64","utf8","certificate"],"backgroundTag":"non-utf8-env-var","analyzedSha":"52e4b6e71d8632a7e648f866c442e287ecddee34","analyzedAt":"2026-08-20T13:59:20.734Z","contentChangedAt":"2026-08-20T13:59:20.734Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}