PrefectHQ/fastmcp · error · RuntimeError
app-bridge.js not found in ext-apps tarball
Error message
app-bridge.js not found in ext-apps tarball
What it means
The dev tooling downloads the @modelcontextprotocol/ext-apps npm tarball and extracts package/dist/src/app-bridge.js from it. tar.extractfile returns None when the member path doesn't exist, which is converted into this RuntimeError. It means the tarball layout changed (path moved/renamed) or the wrong/empty tarball was downloaded.
Source
Thrown at fastmcp_slim/fastmcp/cli/apps_dev.py:1355
# -- Download and patch app-bridge.js (cached per ext-apps + SDK version) -
app_bridge_cache = (
Path(tempfile.gettempdir()) / f"fastmcp-ext-apps-{version}-sdk-{sdk_version}.js"
)
if app_bridge_cache.exists():
app_bridge_js = app_bridge_cache.read_text(encoding="utf-8")
return app_bridge_js, import_map_json
npm_url = f"https://registry.npmjs.org/@modelcontextprotocol/ext-apps/-/ext-apps-{version}.tgz"
with httpx2.Client(timeout=30.0) as client:
resp = client.get(npm_url, follow_redirects=True)
resp.raise_for_status()
data = resp.content
with tarfile.open(fileobj=io.BytesIO(data), mode="r:gz") as tar:
member = tar.extractfile("package/dist/src/app-bridge.js")
if member is None:
raise RuntimeError("app-bridge.js not found in ext-apps tarball")
app_bridge_js = member.read().decode()
# Rewrite bare SDK module specifiers to concrete esm.sh URLs
for sdk_path in ("types.js", "shared/protocol.js"):
app_bridge_js = app_bridge_js.replace(
f'from"@modelcontextprotocol/sdk/{sdk_path}"',
f'from"{sdk_base}/{sdk_path}"',
)
app_bridge_cache.write_text(app_bridge_js, encoding="utf-8")
return app_bridge_js, import_map_json
async def _fetch_app_bridge_bundle(
version: str,
sdk_version: str,
) -> tuple[str, str]:
"""Async wrapper around _fetch_app_bridge_bundle_sync."""View on GitHub (pinned to 1f02114297)
Solutions
- Check the ext-apps version being fetched; pin to a known-good version with app-bridge.js at package/dist/src/
- List the tarball members to find the new path and update the extractfile path in apps_dev.py
- Verify the downloaded bytes are a valid gzip tarball (tar -tzf) — fix registry/proxy issues if not
- Retry after clearing any package cache
Defensive patterns
Strategy: validation
Validate before calling
import io, tarfile
with tarfile.open(fileobj=io.BytesIO(data), mode='r:gz') as tar:
names = tar.getnames()
assert 'package/dist/src/app-bridge.js' in names, names[:20] Try / catch
try:
bundle = _fetch_app_bridge_bundle_sync(...)
except RuntimeError as exc:
if 'app-bridge.js not found' in str(exc):
logger.warning('ext-apps tarball layout changed; pin a known-good version')
else:
raise Prevention
- Pin the ext-apps version instead of floating to latest
- Verify downloaded artifacts are valid gzip tarballs before extracting
- When upgrading ext-apps, diff the package layout
When it happens
Trigger: ext-apps published a new version where app-bridge.js lives at a different path (no dist/src/ layout), or the fetched artifact isn't the expected gzipped package tarball.
Common situations: Unpinned ext-apps version pulling a restructured release; npm registry/proxy returning a 404 page saved as a tarball; offline caches serving stale artifacts.
Related errors
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/e454eedcb048b2dc.
Report an issue: GitHub.