risingwavelabs/risingwave · error

cannot decode user key {} into raw bytes

Error message

cannot decode user key {} into raw bytes

What it means

print_user_key_in_archive expects the user_key argument to be a hex-encoded byte string that decodes into a Hummock UserKey. If hex decoding fails the command panics, since there is no meaningful way to proceed without the key bytes.

Source

Thrown at src/ctl/src/cmd_impl/hummock/validate_version.rs:73

    archive_object_store: ObjectStoreRef,
) -> anyhow::Result<HummockVersionArchive> {
    use prost::Message;
    let archive_dir = version_archive_dir(data_dir);
    let archive_path = format!("{archive_dir}/{archive_id}");
    let archive_bytes = archive_object_store.read(&archive_path, ..).await?;
    let archive: HummockVersionArchive = HummockVersionArchive::decode(archive_bytes)?;
    Ok(archive)
}

pub async fn print_user_key_in_archive(
    context: &CtlContext,
    archive_ids: impl IntoIterator<Item = HummockVersionId>,
    data_dir: String,
    user_key: String,
    use_new_object_prefix_strategy: bool,
) -> anyhow::Result<()> {
    let user_key_bytes = hex::decode(user_key.clone()).unwrap_or_else(|_| {
        panic!("cannot decode user key {} into raw bytes", user_key);
    });
    let user_key = UserKey::decode(&user_key_bytes);
    println!("user key: {user_key:?}");

    let hummock_opts =
        HummockServiceOpts::from_env(Some(data_dir.clone()), use_new_object_prefix_strategy)?;
    let hummock = context.hummock_store(hummock_opts).await?;
    let sstable_store = hummock.sstable_store();
    let archive_object_store = sstable_store.store();
    for archive_id in archive_ids.into_iter().sorted() {
        println!("search archive {archive_id}");
        let archive = get_archive(archive_id, &data_dir, archive_object_store.clone()).await?;
        let mut base_version =
            HummockVersion::from_persisted_protobuf(archive.version.as_ref().unwrap());
        print_user_key_in_version(sstable_store.clone(), &base_version, &user_key).await?;
        for delta in &archive.version_deltas {
            base_version.apply_version_delta(&HummockVersionDelta::from_persisted_protobuf(delta));
            print_user_key_in_version(sstable_store.clone(), &base_version, &user_key).await?;

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Hex-encode the user key before passing it (e.g. `echo -n <bytes> | xxd -p` or using the original hex string from logs)
  2. Check for accidental whitespace or characters outside [0-9a-fA-F] and even length
  3. Re-extract the key from the manifest/SST debug output that provides it in hex

Example fix

// before
rw hummock print-user-key ... --user-key 'row_id=1'
// after
rw hummock print-user-key ... --user-key 'fa1e000001'
Defensive patterns

Strategy: validation

Validate before calling

if user_key.len() % 2 != 0 || !user_key.bytes().all(|b| b.is_ascii_hexdigit()) {
    panic!("user_key must be a hex string");
}

Prevention

When it happens

Trigger: Passing a user_key argument containing non-hex characters or an odd number of characters, e.g. a raw string instead of its hex encoding.

Common situations: Copying a user key from logs and forgetting to hex-encode (or copying only part of it); passing a human-readable key; shell mangling of the argument.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/c57d4c99ebc6ba99. Report an issue: GitHub.