garrytan/gstack · warning · StrictModeError
remote image blocked (offline posture): ${src} — re-run with
Error message
remote image blocked (offline posture): ${src} — re-run without --strict or pass --allow-network What it means
StrictModeError thrown by inlineLocalImages() when an <img src="https://..."> is encountered, --allow-network is not set, AND --strict is set. make-pdf runs in an offline posture by default (Chromium would fetch the URL at print time, leaking and risking inconsistency); strict mode turns the warn into a fatal error so a self-contained PDF is guaranteed.
Source
Thrown at make-pdf/src/diagram-prepass.ts:607
const memo = new Map<string, { dataUri: string; attrs: string }>();
return html.replace(IMG_TAG_RE, (tag) => {
const srcMatch = tag.match(SRC_RE);
if (!srcMatch) return tag;
const src = srcMatch[2] ?? srcMatch[3] ?? "";
if (src.startsWith("data:")) return annotateFromDataUri(tag, src);
// Windows drive-letter paths (C:/x.png, C:\x.png) look like single-letter
// URL schemes — they are local paths, not URLs.
const isDrivePath = /^[a-zA-Z]:[\\/]/.test(src);
if (!isDrivePath && /^[a-z][a-z0-9+.-]*:/i.test(src)) {
// Absolute URL with a scheme (http, https, file, …)
if (opts.allowNetwork && /^https?:/i.test(src)) return tag;
if (/^https?:/i.test(src)) {
const msg = `remote image blocked (offline posture): ${src}`;
if (opts.strict) throw new StrictModeError(msg + " — re-run without --strict or pass --allow-network");
opts.warn(msg);
// Leaving the tag would make Chromium fetch it at print time anyway —
// the warn would be a lie. Replace with a visible placeholder.
return buildBlockedRemotePlaceholder(src);
}
// file:// and friends fall through to the local path branch
if (!src.startsWith("file:")) return tag;
}
// decodeURIComponent throws on malformed escapes (foo%zz.png) — a broken
// URL must degrade to the missing-image path, not crash the run.
let decodedSrc = src;
try {
decodedSrc = decodeURIComponent(src);
} catch { /* keep raw src */ }
const filePath = src.startsWith("file:")
? fileURLToPath(src)View on GitHub (pinned to 94993f7401)
Solutions
- Download the remote image locally and rewrite the markdown src to a relative path.
- Re-run without --strict (it becomes a warn + placeholder) if network independence is not required.
- Pass --allow-network to permit http(s) fetches (Chromium fetches at print time).
- Convert the remote image to a data: URI embedded in the markdown.
Example fix
<!-- before -->  <!-- after: download and reference locally --> 
Defensive patterns
Strategy: validation
Validate before calling
// Scan markdown for remote images before invoking strict mode.
function findRemoteImages(markdown: string): string[] {
const re = /!\[[^\]]*\]\((https?:\/\/[^)]+)\)/g;
const out: string[] = [];
let m: RegExpExecArray | null;
while ((m = re.exec(markdown))) out.push(m[1]);
return out;
}
const remotes = findRemoteImages(markdown);
if (opts.strict && !opts.allowNetwork && remotes.length) {
throw new Error(`strict mode blocks ${remotes.length} remote image(s): ${remotes.join(', ')}`);
} Type guard
import { StrictModeError } from './diagram-prepass';
function isStrictModeError(e: unknown): e is StrictModeError {
return e instanceof StrictModeError;
} Try / catch
try {
inlineLocalImages(html, { strict: true, allowNetwork: false, ... });
} catch (e) {
if (e instanceof StrictModeError && /remote image blocked/.test(e.message)) {
// downgrade to non-strict and accept placeholders
inlineLocalImages(html, { strict: false, allowNetwork: false, ... });
} else throw e;
} Prevention
- Localize all images (download to ./assets) before a strict render.
- Embed small images as data: URIs.
- Only enable --allow-network in trusted, online environments.
- Audit markdown for absolute URLs before CI (`grep -nE '!\\[[^]]*\\]\\(https?://'`).
When it happens
Trigger: inlineLocalImages() with opts.strict=true and opts.allowNetwork=false (or unset), processing markdown containing . The regex matches an absolute http/https URL, the allowNetwork branch is skipped, and the strict branch throws.
Common situations: Running make-pdf --strict on docs that embed a CDN-hosted diagram; a markdown importer that rewrote local paths to absolute URLs; a CI policy mandating --strict for reproducible builds; forgetting to bundle images locally before a strict render.
Related errors
- image not found: ${src} (resolved to ${filePath})
- image resolves OUTSIDE the input directory: ${src} → ${realF
- image is not a regular file: ${src}
- image exceeds ${Math.round(MAX_IMAGE_BYTES / 1024 / 1024)}MB
- invalid proxy URL — could not parse
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/7b781d4480bd5822.
Report an issue: GitHub.