Found during the independent validation run for #45. The two wasm repoints changed not only the URL target but the URL form — and the form matters in the one repo where the reader's browser is the runtime.
What breaks
lecture-wasm executes its code cells in the reader's browser (JupyterLite/Pyodide; the lectures call pyodide_http.patch_all(), so pandas URL reads go through XMLHttpRequest and are subject to CORS on every hop). The github.com/<org>/<repo>/raw/… form is a 302 to raw.githubusercontent.com, and that 302 carries an empty access-control-allow-origin header, which fails the browser's CORS check before the redirect is ever followed. The direct raw.githubusercontent.com form serves access-control-allow-origin: * and works.
Verified empirically with a headless Chromium fetching from the wasm site's own origin (page context https://quantecon.github.io/lecture-wasm/long-run-growth/):
| fetch target |
result |
github.com/QuantEcon/data-lectures/raw/main/lectures/mpd2020.xlsx |
Failed to fetch (CORS) |
github.com/QuantEcon/data-lectures/raw/main/lectures/longprices.xls |
Failed to fetch (CORS) |
github.com/QuantEcon/high_dim_data/raw/main/SCF_plus/SCF_plus_mini_no_weights.csv |
Failed to fetch (CORS) |
raw.githubusercontent.com/QuantEcon/data-lectures/main/lectures/mpd2020.xlsx |
200, 1,765,204 bytes |
raw.githubusercontent.com/QuantEcon/lecture-python-intro/main/lectures/datasets/assignat.xlsx |
200, 209,555 bytes |
Affected
Regressed by the repoints: long_run_growth (QuantEcon/lecture-wasm#52) and inflation_history (QuantEcon/lecture-wasm#53). Before those PRs the wasm copies deliberately used the direct raw.githubusercontent.com form — visible in the diffs, where the wasm branch had diverged from intro's github.com/…/raw/ form precisely on this point. The repoints normalised the wasm URLs to intro's form, which is the one form the wasm runtime cannot fetch.
Same failure, pre-existing: inequality.md (SCF_plus_mini.csv) and mle.md (SCF_plus_mini_no_weights.csv) read via github.com/QuantEcon/high_dim_data/raw/…, so their in-browser reads were already broken before the migration. heavy_tails.md is fine — media.githubusercontent.com (the LFS media host) is CORS-clean.
The repoints themselves were necessary and correctly sequenced — the old wasm URLs pointed at intro's local copies, which QuantEcon/lecture-python-intro#825 has now deleted. Only the URL form is wrong.
Scope notes
The {download} link and prose links are plain navigations; CORS does not apply to them. The intro site and Colab are unaffected — real CPython, no CORS. The static wasm pages render (200), but the wasm build bakes no outputs, so figures and dataframes exist only after in-browser execution — which now fails at the first data cell of these two lectures. This is also why nothing in CI caught it: the break exists only inside a reader's browser.
Fix and rule
Flip the wasm reads to https://raw.githubusercontent.com/QuantEcon/data-lectures/main/lectures/<file> (and the SCF reads likewise when high_dim_data folds in). Then add to PLAN's repoint rules: in lecture-wasm, data URLs must use a CORS-clean host — raw.githubusercontent.com, or media.githubusercontent.com for LFS-tracked files — never the github.com/<org>/<repo>/raw/ redirect form.
Phase 4 inherits the same requirement: data.quantecon.org must serve access-control-allow-origin: *, or the wasm repo cannot cut over to it. Worth recording on #37 so the DNS work picks it up as an acceptance criterion.
Reproduce with any browser console on a quantecon.github.io page: fetch('https://github.com/QuantEcon/data-lectures/raw/main/lectures/mpd2020.xlsx') rejects; the raw.githubusercontent.com equivalent resolves.
Found during the independent validation run for #45. The two wasm repoints changed not only the URL target but the URL form — and the form matters in the one repo where the reader's browser is the runtime.
What breaks
lecture-wasmexecutes its code cells in the reader's browser (JupyterLite/Pyodide; the lectures callpyodide_http.patch_all(), so pandas URL reads go through XMLHttpRequest and are subject to CORS on every hop). Thegithub.com/<org>/<repo>/raw/…form is a 302 toraw.githubusercontent.com, and that 302 carries an emptyaccess-control-allow-originheader, which fails the browser's CORS check before the redirect is ever followed. The directraw.githubusercontent.comform servesaccess-control-allow-origin: *and works.Verified empirically with a headless Chromium fetching from the wasm site's own origin (page context
https://quantecon.github.io/lecture-wasm/long-run-growth/):github.com/QuantEcon/data-lectures/raw/main/lectures/mpd2020.xlsxgithub.com/QuantEcon/data-lectures/raw/main/lectures/longprices.xlsgithub.com/QuantEcon/high_dim_data/raw/main/SCF_plus/SCF_plus_mini_no_weights.csvraw.githubusercontent.com/QuantEcon/data-lectures/main/lectures/mpd2020.xlsxraw.githubusercontent.com/QuantEcon/lecture-python-intro/main/lectures/datasets/assignat.xlsxAffected
Regressed by the repoints:
long_run_growth(QuantEcon/lecture-wasm#52) andinflation_history(QuantEcon/lecture-wasm#53). Before those PRs the wasm copies deliberately used the directraw.githubusercontent.comform — visible in the diffs, where the wasm branch had diverged from intro'sgithub.com/…/raw/form precisely on this point. The repoints normalised the wasm URLs to intro's form, which is the one form the wasm runtime cannot fetch.Same failure, pre-existing:
inequality.md(SCF_plus_mini.csv) andmle.md(SCF_plus_mini_no_weights.csv) read viagithub.com/QuantEcon/high_dim_data/raw/…, so their in-browser reads were already broken before the migration.heavy_tails.mdis fine —media.githubusercontent.com(the LFS media host) is CORS-clean.The repoints themselves were necessary and correctly sequenced — the old wasm URLs pointed at intro's local copies, which QuantEcon/lecture-python-intro#825 has now deleted. Only the URL form is wrong.
Scope notes
The
{download}link and prose links are plain navigations; CORS does not apply to them. The intro site and Colab are unaffected — real CPython, no CORS. The static wasm pages render (200), but the wasm build bakes no outputs, so figures and dataframes exist only after in-browser execution — which now fails at the first data cell of these two lectures. This is also why nothing in CI caught it: the break exists only inside a reader's browser.Fix and rule
Flip the wasm reads to
https://raw.githubusercontent.com/QuantEcon/data-lectures/main/lectures/<file>(and the SCF reads likewise whenhigh_dim_datafolds in). Then add to PLAN's repoint rules: inlecture-wasm, data URLs must use a CORS-clean host —raw.githubusercontent.com, ormedia.githubusercontent.comfor LFS-tracked files — never thegithub.com/<org>/<repo>/raw/redirect form.Phase 4 inherits the same requirement:
data.quantecon.orgmust serveaccess-control-allow-origin: *, or the wasm repo cannot cut over to it. Worth recording on #37 so the DNS work picks it up as an acceptance criterion.Reproduce with any browser console on a
quantecon.github.iopage:fetch('https://github.com/QuantEcon/data-lectures/raw/main/lectures/mpd2020.xlsx')rejects; theraw.githubusercontent.comequivalent resolves.