Skip to content

fix(media): normalize urlsafe base64 for media uploads#1766

Open
MJRuskin wants to merge 1 commit into
langfuse:mainfrom
MJRuskin:fix/normalize_b64_media
Open

fix(media): normalize urlsafe base64 for media uploads#1766
MJRuskin wants to merge 1 commit into
langfuse:mainfrom
MJRuskin:fix/normalize_b64_media

Conversation

@MJRuskin

@MJRuskin MJRuskin commented Jul 17, 2026

Copy link
Copy Markdown

What does this PR do?

langfuse/langfuse#15179

Fixes compatibility issues with openinference package, which uses urlsafe base64 in certain output fields.
Normalizes the base64 string during the parse function.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Refactor
  • Documentation update
  • Tooling, CI, or repo maintenance

Verification

List the main commands you ran:

Checklist

  • I self-reviewed the diff using code_review.md.
  • I added or updated tests for behavior changes.
  • I updated docs, examples, or .env.template if needed.
  • I did not hand-edit generated files; if generated files changed, I used the upstream regeneration path.
  • I did not commit secrets or credentials.

Greptile Summary

This PR fixes a compatibility bug where media uploads would fail when the base64 payload used the URL-safe alphabet (- and _ instead of + and /), as produced by the openinference package. The fix normalizes the incoming base64 string before decoding.

  • Normalization logic: actual_data.replace("-", "+").replace("_", "/") is applied before base64.b64decode, converting URL-safe base64 to standard base64. This is functionally correct; an equally valid (and more idiomatic) alternative is base64.urlsafe_b64decode.
  • No padding handling added: Both the old and new code assume the base64 string is properly padded with =; if openinference ever omits padding the call will still raise and be swallowed by the outer except block.

Confidence Score: 4/5

Safe to merge — the change is a one-line normalization that fixes a real compatibility gap and degrades gracefully on failure.

The normalization logic is correct and the error path is already guarded by the outer try/except. The only gaps are a missed opportunity to use the stdlib urlsafe_b64decode and the absence of unit tests for the new code path.

langfuse/media.py — worth adding a unit test in tests/unit/test_media.py that covers URL-safe encoded inputs.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Caller
    participant LangfuseMedia
    participant base64

    Caller->>LangfuseMedia: _parse_base64_data_uri(data_uri)
    LangfuseMedia->>LangfuseMedia: "validate 'data:' prefix & split header/body"
    LangfuseMedia->>LangfuseMedia: check 'base64' in header parts
    Note over LangfuseMedia: NEW: normalize URL-safe chars<br/>replace('-','+').replace('_','/')
    LangfuseMedia->>base64: b64decode(normalized_data)
    base64-->>LangfuseMedia: raw bytes
    LangfuseMedia-->>Caller: (bytes, content_type)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Caller
    participant LangfuseMedia
    participant base64

    Caller->>LangfuseMedia: _parse_base64_data_uri(data_uri)
    LangfuseMedia->>LangfuseMedia: "validate 'data:' prefix & split header/body"
    LangfuseMedia->>LangfuseMedia: check 'base64' in header parts
    Note over LangfuseMedia: NEW: normalize URL-safe chars<br/>replace('-','+').replace('_','/')
    LangfuseMedia->>base64: b64decode(normalized_data)
    base64-->>LangfuseMedia: raw bytes
    LangfuseMedia-->>Caller: (bytes, content_type)
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
langfuse/media.py:294-296
Python's standard library already provides `base64.urlsafe_b64decode`, which performs exactly this alphabet substitution (`-``+`, `_``/`) internally. Using it directly is more idiomatic and makes the intent self-documenting.

```suggestion
            return base64.urlsafe_b64decode(actual_data), cast(MediaContentType, content_type)
```

### Issue 2 of 2
langfuse/media.py:294-296
**Missing test coverage for URL-safe base64 inputs.** The PR checklist acknowledges no tests were added. `tests/unit/test_media.py` has no case exercising the `-` and `_` substitution path, so a future regression (e.g. re-introduction of `b64decode` without normalisation) would go undetected. Consider adding a unit test that passes a URL-safe encoded data URI and asserts the decoded bytes match the expected output.

Reviews (1): Last reviewed commit: "fix(media): normalize urlsafe base64 for..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@CLAassistant

CLAassistant commented Jul 17, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Comment thread langfuse/media.py
Comment on lines +294 to +296
normalized_data = actual_data.replace("-", "+").replace("_", "/")

return base64.b64decode(normalized_data), cast(MediaContentType, content_type)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing test coverage for URL-safe base64 inputs. The PR checklist acknowledges no tests were added. tests/unit/test_media.py has no case exercising the - and _ substitution path, so a future regression (e.g. re-introduction of b64decode without normalisation) would go undetected. Consider adding a unit test that passes a URL-safe encoded data URI and asserts the decoded bytes match the expected output.

Prompt To Fix With AI
This is a comment left during a code review.
Path: langfuse/media.py
Line: 294-296

Comment:
**Missing test coverage for URL-safe base64 inputs.** The PR checklist acknowledges no tests were added. `tests/unit/test_media.py` has no case exercising the `-` and `_` substitution path, so a future regression (e.g. re-introduction of `b64decode` without normalisation) would go undetected. Consider adding a unit test that passes a URL-safe encoded data URI and asserts the decoded bytes match the expected output.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants