---
title: "lameenc Returns bytearray, Not bytes — GCS Upload TypeError"
aliases: [lameenc-bytearray, lameenc-gcs, lameenc-type-error]
tags: [python, audio, gcs, lameenc, gotcha, celery]
sources:
  - "daily/2026-04-30.md"
created: 2026-04-30
updated: 2026-04-30
---

# lameenc Returns bytearray, Not bytes — GCS Upload TypeError

`lameenc.encode()` returns `bytearray`, not `bytes`. Passing this directly to `google.cloud.storage blob.upload_from_string()` raises a `TypeError` whose message is the raw bytes representation — looks like corrupt data but is actually a type check failure.

## Key Points

- `lameenc.encode()` and `lameenc.flush()` return `bytearray`, not `bytes`
- `blob.upload_from_string(bytearray_value)` raises `TypeError` — the error message displays the raw bytearray repr, making it look like data corruption
- Fix: `bytes(lameenc_output)` cast before passing to any GCS or HTTP upload function
- When all Celery retries fail identically, the error is deterministic — type errors and wrong data shapes don't get better on retry; Redis queue flush is required to unblock

## Details

### The Misleading Error

```python
mp3_data = encoder.encode(pcm_bytes) + encoder.flush()
# mp3_data is bytearray, not bytes

blob.upload_from_string(mp3_data, content_type="audio/mpeg")
# Raises: TypeError: <bytearray object at 0x...> (raw bytes repr in error message)
```

The `TypeError` message appears to show corrupted binary content rather than a clear type mismatch, leading to false diagnosis of encoding errors or data corruption.

### The Fix

```python
mp3_data = encoder.encode(pcm_bytes) + encoder.flush()
mp3_bytes = bytes(mp3_data)  # explicit cast

blob.upload_from_string(mp3_bytes, content_type="audio/mpeg")
```

### Celery Retry Loop Implication

A `TypeError` is deterministic — every retry will fail in exactly the same way. When you see:
- All Celery retries exhausted with identical errors
- Job completion counter stays at 0

This is not a transient issue. The fix requires:
1. Fixing the code (cast to `bytes`)
2. Flushing Redis to clear the failed task IDs
3. Re-enqueueing the job

See [[wiki/concepts/celery-redis-queue-flush-on-deterministic-error]] for the Redis flush procedure.

### Why bytearray vs bytes Matters

Both `bytearray` and `bytes` are binary sequences in Python, but many C-extension libraries and GCS client internals do an explicit `isinstance(data, bytes)` check rather than checking for the buffer protocol. `bytearray` fails that check.

## Related Concepts

- [[wiki/concepts/pydub-ffmpeg-silent-dependency]] — the alternative (pydub) and why lameenc was chosen
- [[wiki/concepts/celery-redis-queue-flush-on-deterministic-error]] — flushing Redis when deterministic errors fill the retry queue

## Sources

- [[daily/2026-04-30.md]] — Session 19:35, lameenc bytearray TypeError in GCS upload
