ComposioHQ/composio · error · KeyringError

BadEncoding

BadEncoding

Error message

BadEncoding

What it means

Entry.getPassword() failed to UTF-8 decode the stored secret bytes. The credential was stored as opaque binary (via setSecret) and is not valid UTF-8 text, so decoding it as a password string raises KeyringError kind 'BadEncoding'.

Source

Thrown at ts/packages/cli-keyring/src/core/entry.ts:84

   * Store `password` as UTF-8 bytes under this entry's specifier.
   * Overwrites any existing value.
   */
  async setPassword(password: string): Promise<void> {
    await this.setSecret(textEncoder.encode(password));
  }

  /**
   * Fetch the stored value and decode it as UTF-8. Throws
   * `KeyringError({ kind: 'NoEntry' })` if nothing was stored, or
   * `KeyringError({ kind: 'BadEncoding', bytes })` if the stored bytes
   * aren't valid UTF-8 — matching keyring-rs's `Error::BadEncoding`.
   */
  async getPassword(): Promise<string> {
    const bytes = await this.getSecret();
    try {
      return textDecoder.decode(bytes);
    } catch {
      throw new KeyringError({ kind: 'BadEncoding', bytes });
    }
  }

  /** Store raw bytes. */
  async setSecret(secret: Uint8Array): Promise<void> {
    await this.resolveStore().setSecret(this.service, this.user, secret, this.modifiers);
  }

  /** Fetch raw bytes. Throws `NoEntry` if nothing matches. */
  async getSecret(): Promise<Uint8Array> {
    return this.resolveStore().getSecret(this.service, this.user, this.modifiers);
  }

  /** Delete the credential. Throws `NoEntry` if it didn't exist. */
  async deleteCredential(): Promise<void> {
    await this.resolveStore().deleteCredential(this.service, this.user, this.modifiers);
  }

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Use getSecret() to read raw bytes instead of getPassword() when the value is binary
  2. Store text via setPassword() if a string is expected later
  3. Delete and re-store the entry if it is corrupted

Example fix

// before
const pw = await entry.getPassword();
// after
const bytes = await entry.getSecret(); // handle as binary
Defensive patterns

Strategy: type-guard

Validate before calling

// Prefer bytes API when value may be binary
const bytes = await entry.getSecret();

Try / catch

catch (e) { if (e instanceof KeyringError && e.kind === 'BadEncoding') { return await entry.getSecret(); } throw e; }

Prevention

When it happens

Trigger: Calling getPassword() on an entry whose secret was written with setSecret(binaryUint8) containing non-UTF-8 bytes.

Common situations: Mixing binary secret storage (tokens, keys) with the string-oriented getPassword API; corrupted keychain entries.

Related errors


AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28). Data as JSON: /api/errors/9c34c6a9a9d9a2eb. Report an issue: GitHub.