Agent skill

Proxy Range Header Forwarding

by divinevideo in divinevideo/divine-mobile

Fix iOS AVPlayer "CoreMediaErrorDomain error -12939 - byte range length mismatch" or similar video streaming failures when a proxy/edge/CDN service sits between the client and object storage (GCS…

MPL-2.0Auto-check passedBackend & APIs

Install Proxy Range Header Forwarding

skills CLI
$ npx skills add divinevideo/divine-mobile --skill proxy-range-header-forwarding -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install divinevideo/divine-mobile proxy-range-header-forwarding --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/divinevideo/divine-mobile.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/proxy-range-header-forwarding .claude/skills/proxy-range-header-forwarding && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
proxy-range-header-forwarding
GitHub stars
266
Token cost
~1.6k tokens
SKILL.md length
457 words
Files
1
Skills in repo
103
Repo updated
First seen
Licence
MPL-2.0

At a glance

Fix iOS AVPlayer "CoreMediaErrorDomain error -12939 - byte range length mismatch" or similar video streaming failures when a proxy/edge/CDN service sits between the client and object storage (GCS…

  • Works in 3 steps: Extract Range header from client request → Forward Range header to storage backend → Accept 206 responses from the backend
  • IOS video fails with -12939 byte range length mismatch - should be length 2 is length N
  • SKILL.md covers Problem, Context / Trigger Conditions, Root Cause Pattern and Solution, plus 4 more sections
  • Calls curl

What it does

Proxy Range Header Forwarding is an agent skill from divinevideo/divine-mobile. Fix iOS AVPlayer "CoreMediaErrorDomain error -12939 - byte range length mismatch" or similar video streaming failures when a proxy/edge/CDN service sits between the client and object storage (GCS, S3, R2). Use when: (1) iOS video fails with -12939 "byte range length mismatch - should be length 2 is length N", (2) curl with Range: bytes=0-1 returns full file instead of 2 bytes, (3) one URL path works with Range but another path to the same storage doesn't, (4) proxy advertises Accept-Ranges: bytes but returns 200…

Its SKILL.md is about 1.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Backend & APIs, covering File uploads and storage and Root cause analysis. It works with iOS. The licence is MPL-2.0.

When your agent uses it

  • IOS video fails with -12939 byte range length mismatch - should be length 2 is length N
  • Curl with Range: bytes=0-1 returns full file instead of 2 bytes
  • One URL path works with Range but another path to the same storage doesnt
  • Proxy advertises Accept-Ranges: bytes but returns 200 with full file for range requests

Example prompts

  • “CoreMediaErrorDomain error -12939 - byte range length mismatch”
  • “byte range length mismatch - should be length 2 is length N”
  • “/proxy-range-header-forwarding”

Workflow steps

3 steps, taken from the step headings in SKILL.md.

  1. Extract Range header from client request
  2. Forward Range header to storage backend
  3. Accept 206 responses from the backend

What it can do on your machine

Read from SKILL.md and the folder at commit 4c622be. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • curl

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • developer.mozilla.org
    • cloud.google.com
    • developer.apple.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Proxy Range Header Forwarding loads about 1.6k tokens when it runs. Until then it costs about 179 tokens; SKILL.md has 457 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~179
When it runs · the whole SKILL.md, loaded when a task matches
~1.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from divinevideo/divine-mobile at commit 4c622be, republished under its MPL-2.0 licence (© divinevideo). 457 words, ~1,560 tokens.

Download SKILL.mdSave it as .claude/skills/proxy-range-header-forwarding/SKILL.md (or your agent's skills folder).
name
proxy-range-header-forwarding
description
Fix iOS AVPlayer "CoreMediaErrorDomain error -12939 - byte range length mismatch" or similar video streaming failures when a proxy/edge/CDN service sits between the client and object storage (GCS, S3, R2). Use when: (1) iOS video fails with -12939 "byte range length mismatch - should be length 2 is length N", (2) curl with Range: bytes=0-1 returns full file instead of 2 bytes, (3) one URL path works with Range but another path to the same storage doesn't, (4) proxy advertises Accept-Ranges: bytes but returns 200 with full file for range requests. The root cause is typically a proxy handler that constructs a new request to the backend without forwarding the client's Range header.
author
Claude Code
version
1.0.0
date
2026-02-22

Proxy Range Header Forwarding for Video Streaming

Problem

A proxy/edge service (Fastly Compute, Cloudflare Workers, custom reverse proxy) sits between clients and object storage. Some routes correctly forward HTTP Range headers to the storage backend, but other routes (added later or by different developers) construct backend requests from scratch without forwarding Range headers. This causes iOS AVPlayer to fail because it probes with Range: bytes=0-1 and rejects responses where the body size doesn't match the requested range.

Context / Trigger Conditions

  • iOS error: CoreMediaErrorDomain error -12939 - byte range length mismatch - should be length 2 is length N
  • PlatformException(VideoError, Failed to load video: Operation Stopped)
  • curl -H "Range: bytes=0-1" on the failing URL returns 200 with Content-Length equal to full file size
  • The same curl test on a different URL path to the same storage returns 206 with Content-Length: 2
  • The proxy/edge code has multiple route handlers that independently construct backend requests
  • Response headers include Accept-Ranges: bytes (misleadingly advertising support)

Root Cause Pattern

In proxy architectures, each route handler independently constructs requests to the storage backend. It's common for the "original" handler to properly forward Range headers while variant handlers (quality variants, thumbnails, transcoded versions) build requests from scratch without considering Range.

rust
// BROKEN: Handler ignores client Range header
fn handle_variant(req: Request, path: &str) -> Response {
    let gcs_path = resolve_variant(path);
    let backend_req = Request::new(Method::GET, &gcs_url);  // No Range header!
    backend_req.send("storage")
}

// WORKING: Handler forwards Range header
fn handle_original(req: Request, path: &str) -> Response {
    let range = req.get_header("Range");  // Extracts Range
    let backend_req = Request::new(Method::GET, &gcs_url);
    if let Some(r) = range {
        backend_req.set_header("Range", r);  // Forwards it
    }
    backend_req.send("storage")
}

Solution

Three things must all be fixed in the proxy handler:

1. Extract Range header from client request
rust
let range = req
    .get_header(header::RANGE)
    .and_then(|h| h.to_str().ok())
    .map(|s| s.to_string());
2. Forward Range header to storage backend
rust
if let Some(range_value) = range {
    backend_req.set_header("Range", range_value);
}
3. Accept 206 responses from the backend
rust
// BEFORE (broken): only accepts 200
match resp.get_status() {
    StatusCode::OK => Ok(resp),
    ...
}

// AFTER (fixed): accepts both 200 and 206
match resp.get_status() {
    StatusCode::OK | StatusCode::PARTIAL_CONTENT => Ok(resp),
    ...
}

GCS/S3/R2 natively handle Range headers and return proper 206 Partial Content with correct Content-Range and Content-Length headers, so once forwarded, the response can be passed through directly to the client.

Verification

bash
# Test the failing endpoint with a range probe (what iOS does)
curl -sv -H "Range: bytes=0-1" "https://cdn.example.com/hash/variant" \
  -o /dev/null 2>&1 | grep -iE "< HTTP|content-length|content-range"

# Expected AFTER fix:
# < HTTP/2 206
# < content-range: bytes 0-1/TOTAL_SIZE
# < content-length: 2

# Test mid-file range
curl -sv -H "Range: bytes=1000-1999" "https://cdn.example.com/hash/variant" \
  -o /dev/null 2>&1 | grep -iE "< HTTP|content-length|content-range"

# Expected: 206, content-length: 1000, content-range: bytes 1000-1999/TOTAL

# Test full download still works (no Range header)
curl -sv "https://cdn.example.com/hash/variant" \
  -o /dev/null 2>&1 | grep -iE "< HTTP|content-length"

# Expected: 200, content-length: TOTAL_SIZE
Show full SKILL.md (194 more words)Show less

Example

Real case: Fastly Compute edge service proxying to GCS. The /{hash} route (original blob) forwarded Range headers via download_blob(hash, range). The /{hash}/720p route (transcoded quality variant) called download_hls_from_gcs(gcs_key) with no range parameter.

Fix required changes in three layers:

  1. Storage function: added range: Option<&str> parameter
  2. Wrapper function: passed range through
  3. Route handler: extracted Range from client request

Notes

  • Audit all route handlers: If one handler is missing Range forwarding, others likely are too. Search for all places that construct backend requests and verify Range is forwarded.
  • Don't just set Accept-Ranges: Adding Accept-Ranges: bytes to responses without actually handling ranges is worse than not advertising it - clients will expect it to work.
  • iOS is strict: Safari/AVPlayer always probes with Range: bytes=0-1 before streaming. Chrome/Android are more forgiving and may work without proper Range support.
  • HEAD requests: HEAD handlers don't need Range forwarding (they return metadata only), but GET handlers absolutely do.
  • Cache layers: If a caching proxy sits in front, it may cache the full 200 response and serve it for Range requests. Purge cache after deploying the fix.

References

© divinevideo, MPL-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/proxy-range-header-forwarding of divinevideo/divine-mobile.

Open the folder on GitHubat commit 4c622be

Compare with similar skills

Proxy Range Header Forwarding next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Proxy Range Header Forwarding compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Proxy Range Header Forwarding this skilldivinevideo/divine-mobile266—~1.6kAutomated safety check: PassMPL-2.0
Reverse Flowlingbol088-spec/reverse-flow-skill936—~2.4kAutomated safety check: PassMIT
iOS FixMacMagazine/app-iOS171—~957Automated safety check: PassNone
Fix GitHub IssueShopify/flash-list7.2k—~1.6kAutomated safety check: PassMIT
AppsFlyer Unity Bridge DebuggingAppsFlyerSDK/appsflyer-unity-plugin178—~492Automated safety check: PassMIT
iOS Memgraph Leaksomarshahine/HomeClaw1761 repos~1kAutomated safety check: PassMIT

Similar skills

  • Reverse Flow

    lingbol088-spec/reverse-flow-skill

    Guided reverse engineering workflow for binaries, firmware, mobile apps, scripts, document samples, protocol captures, and unknown artifacts.

    936 GitHub stars~2.4k tokensUpdated 2 mo ago
    SecurityAuto-check passed
  • iOS Fix

    MacMagazine/app-iOS

    Bug-fix and refactoring workflow for MacMagazine — root cause analysis, pattern-matching fix, regression verification.

    171 GitHub stars~957 tokensUpdated today
    DevelopmentAuto-check passed
  • Fix GitHub Issue

    Shopify/flash-list

    Official

    Full workflow for fixing a GitHub issue - understand the problem, reproduce, diagnose root cause, fix, test on iOS/Android simulators, review, and raise a PR

    7.2k GitHub stars~1.6k tokensUpdated 6 days ago
    DevelopmentAuto-check passed
  • AppsFlyer Unity Bridge Debugging

    AppsFlyerSDK/appsflyer-unity-plugin

    Traces a failing call or callback between C# and the native Android or iOS wrappers of the AppsFlyer Unity plugin to find the first broken link.

    178 GitHub stars~492 tokensUpdated 3 days ago
    DevelopmentAuto-check passed
  • iOS Memgraph Leaks

    omarshahine/HomeClaw

    Capture, inspect, compare, and root-cause iOS memory graph leaks using Apple's leaks and memgraph tools.

    176 GitHub starsUsed in 1 repo~1k tokens
    DevelopmentAuto-check passed
  • Investigate CI

    ClickHouse/ClickHouse

    Investigate a ClickHouse CI failure end-to-end from a PR or S3 report URL.

    50k GitHub stars~11k tokensUpdated today
    DatabasesAuto-check: notes

More from divinevideo/divine-mobile

All 103 skills in this repo
  • Fix ArgoCD ExternalSecret deployment failing with "namespace X is not permitted in project Y".

    266 GitHub stars~931 tokensUpdated today
    Auto-check passed
  • Art Direct

    divinevideo/divine-mobile

    Art direction for any content — reads text, PDF, Word, HTML, PPT, then proposes 2-3 creative directions with photography style, mood, and visual language.

    266 GitHub stars~4.8k tokensUpdated today
    Auto-check passed
  • Async Await Null Race Condition

    divinevideo/divine-mobile

    Fix "Null check operator used on a null value" errors when an object is set to null during an async await.

    266 GitHub stars~881 tokensUpdated today
    Auto-check passed
  • AWS V4 Signing Custom Headers Gcs

    divinevideo/divine-mobile

    Add custom metadata headers (x-amz-meta-) to AWS v4 signed requests for GCS S3-compatible API.

    266 GitHub stars~1k tokensUpdated today
    Auto-check passed
  • Bash Herestring Newline Secrets

    divinevideo/divine-mobile

    Fix password/secret authentication failures caused by trailing newlines when creating Google Cloud secrets (or similar) with bash here-strings.

    266 GitHub stars~791 tokensUpdated today
    Auto-check passed
  • Fix silent video/media processing failures caused by URL extraction code that filters on file extensions (.mp4, .webm, .webp).

    266 GitHub stars~1.1k tokensUpdated today
    Auto-check passed

Works with

Categories

Questions about Proxy Range Header Forwarding

What does Proxy Range Header Forwarding do?

Fix iOS AVPlayer "CoreMediaErrorDomain error -12939 - byte range length mismatch" or similar video streaming failures when a proxy/edge/CDN service sits between the client and object storage (GCS…. Proxy Range Header Forwarding is an agent skill from divinevideo/divine-mobile. Fix iOS AVPlayer "CoreMediaErrorDomain error -12939 - byte range length mismatch" or similar video streaming failures when a proxy/edge/CDN service sits between the client and object storage (GCS, S3, R2).

When should I use Proxy Range Header Forwarding?

Proxy Range Header Forwarding fits situations like: IOS video fails with -12939 byte range length mismatch - should be length 2 is length N; curl with Range: bytes=0-1 returns full file instead of 2 bytes; one URL path works with Range but another path to the same storage doesnt; proxy advertises Accept-Ranges: bytes but returns 200 with full file for range requests.

How do I install Proxy Range Header Forwarding in Claude Code?

Run `npx skills add divinevideo/divine-mobile --skill proxy-range-header-forwarding -a claude-code`. Or copy the skill folder (.agents/skills/proxy-range-header-forwarding in divinevideo/divine-mobile) into .claude/skills/proxy-range-header-forwarding in your project. Claude Code loads it when a task matches its description.

How do I install Proxy Range Header Forwarding in Codex?

Run `npx skills add divinevideo/divine-mobile --skill proxy-range-header-forwarding -a codex`. Or copy the skill folder (.agents/skills/proxy-range-header-forwarding in divinevideo/divine-mobile) into .agents/skills/proxy-range-header-forwarding in your project. Codex loads it when a task matches its description.

Can I use Proxy Range Header Forwarding in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add divinevideo/divine-mobile --skill proxy-range-header-forwarding -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/proxy-range-header-forwarding, .gemini/skills/proxy-range-header-forwarding, .github/skills/proxy-range-header-forwarding and .opencode/skills/proxy-range-header-forwarding in your project.

What does Proxy Range Header Forwarding need to run?

Going by SKILL.md and its folder, Proxy Range Header Forwarding needs the command-line tools its instructions call (curl).

Does Proxy Range Header Forwarding access the network?

SKILL.md names 3 domains. As links in the text: developer.mozilla.org, cloud.google.com and developer.apple.com. This is read from the text; nothing was executed.

Is Proxy Range Header Forwarding safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Proxy Range Header Forwarding use?

Proxy Range Header Forwarding is published under the MPL-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Proxy Range Header Forwarding use?

About 1.6k tokens (SKILL.md is roughly 6.2k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Proxy Range Header Forwarding?

Skills that share tags, products or a category with Proxy Range Header Forwarding: Reverse Flow (lingbol088-spec/reverse-flow-skill, 936 stars), iOS Fix (MacMagazine/app-iOS, 171 stars), Fix GitHub Issue (Shopify/flash-list, 7.2k stars) and AppsFlyer Unity Bridge Debugging (AppsFlyerSDK/appsflyer-unity-plugin, 178 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Proxy Range Header Forwarding?

divinevideo (a GitHub organization) maintains it in divinevideo/divine-mobile, which has 266 GitHub stars. The repository holds 103 skills in this directory. The repository was last updated on October 8, 2026.

Source: divinevideo/divine-mobile on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.