Known Issue: Image Block storageKey Stores CDN URL Instead of Blob Pathname
Known Issue: Image Block storageKey Stores CDN URL Instead of Blob Pathname
Status: Identified — fix pending
Affects: Courses imported from Teachable via the Inngest import pipeline
First reported: v1.0.49
Summary
When a Teachable course is imported through the platform's Inngest-based import pipeline, image blocks within lesson pages are constructed with an incorrect value in their storageKey field. The field is populated with the full Vercel Blob CDN URL rather than the relative Blob storage pathname that the rest of the system expects.
This means image assets created during a Teachable import are not correctly registered with the asset lifecycle management system and cannot be tracked, purged, or managed through the standard asset pipeline.
Technical Detail
During import materialisation (import-materialize.ts), after source images are uploaded to Vercel Blob storage, the migration step returns a CDN URL of the form:
https://<account-hash>.public.blob.vercel-storage.com/imports/abc123/image.png
The current (buggy) code assigns this URL directly to storageKey:
// ❌ What the code currently does
imageBlock.storageKey = raw.image.src; // CDN URL after migration
However, storageKey is defined system-wide as the relative pathname within Blob storage (e.g. imports/abc123/image.png). This is the key used by:
- The asset purge / cleanup pipeline when deleting unreferenced blobs
- The asset audit system when reconciling stored objects
- Any future re-signing or access-control layer that needs to resolve a blob by path
Because the stored value is a full URL rather than a pathname, lookups against assets.storageKey for these image blocks will silently fail.
Impact
What works
- Images display correctly in the course viewer. The CDN URL stored in
storageKeyis still a valid public URL, so<img>tags render without issue.
What is broken
- Asset purge pipeline — image blobs from Teachable imports will not be found by
storageKeylookups and will never be cleaned up, leading to orphaned blobs in storage. - Asset lifecycle tracking — these assets appear invisible to management tooling.
- Data consistency —
storageKeyvalues across the system are mixed (some relative paths, some full URLs), which complicates any future migration or query.
Workaround
There is currently no end-user workaround. Imported image content will display normally. However, be aware that storage costs may accumulate if large volumes of Teachable course images are imported before the fix is deployed, since orphaned blobs will not be purged.
Planned Fix
The fix involves updating import-materialize.ts so that after the asset migration step, the code looks up the corresponding import_assets row by source URL and retrieves the pre-recorded storageKey (relative pathname). The CDN URL continues to be used for rendering purposes but is no longer written into the storageKey column.
// ✅ Intended behaviour after fix
const importAsset = await db.importAsset.findFirst({
where: { importId, srcUrl: raw.image.src }
});
imageBlock.storageKey = importAsset.storageKey; // e.g. "imports/abc123/image.png"
Affected Components
| Component | File | Nature of issue |
|---|---|---|
| Import materialisation | src/inngest/functions/import-materialize.ts | storageKey assigned CDN URL instead of Blob pathname |
| Asset purge pipeline | (consumer) | Lookup by storageKey fails for affected image blocks |