windmill-labs/windmill · error · Error

Invalid PDF source object${typeof source}

Error message

Invalid PDF source object${typeof source}

What it means

AppPdf.svelte's loadSource() validates the PDF display component's source: it must be a string URL or an ArrayBuffer. Anything else truthy (object, array, blob-like) throws 'Invalid PDF source object<type>'.

Source

Thrown at frontend/src/lib/components/apps/components/display/AppPdf.svelte:50

	let pdfSource: string | ArrayBuffer | undefined = $state(undefined)

	let token = getContext<{ token?: string }>('AuthToken')

	async function loadSource() {
		if (isPartialS3Object(source)) {
			pdfSource = await getS3File({
				source: source.s3,
				storage: source.storage,
				presigned: source.presigned,
				appPath: $appPath,
				username: $userStore?.username,
				workspace,
				token: token?.token,
				isEditor,
				configuration
			})
		} else if (source && typeof source !== 'string' && !(source instanceof ArrayBuffer)) {
			throw new Error('Invalid PDF source object' + typeof source)
		} else if (typeof source === 'string' && source?.startsWith('s3://')) {
			pdfSource = await getS3File({
				source: source?.replace('s3://', ''),
				appPath: $appPath,
				username: $userStore?.username,
				workspace,
				token: token?.token,
				isEditor,
				configuration
			})
		} else {
			pdfSource = source
		}
	}

	$effect(() => {
		source && loadSource()
	})

View on GitHub (pinned to e474e8803c)

Solutions

  1. Make the source resolve to a string URL (e.g. result.url) or convert the payload to an ArrayBuffer before assigning it
  2. If the step returns binary, fetch the URL and pass response.arrayBuffer()
  3. Check that the s3:// string form is used for workspace-stored PDFs

Example fix

// before
source: `${inputs1.result}` // object
// after
source: await inputs1.result.arrayBuffer()
Defensive patterns

Strategy: validation

Validate before calling

if (source && typeof source !== 'string' && !(source instanceof ArrayBuffer)) {
  throw new TypeError(`PDF source must be string or ArrayBuffer, got ${typeof source}`)
}

Type guard

function isValidPdfSource(s: unknown): s is string | ArrayBuffer {
  return typeof s === 'string' || s instanceof ArrayBuffer
}

Try / catch

try {
  await loadSource()
} catch (e) {
  if (e.message.startsWith('Invalid PDF source object')) {
    console.error('PDF source must be a URL string or ArrayBuffer', e)
  } else throw e
}

Prevention

When it happens

Trigger: A PDF viewer component whose source config resolves to a non-string, non-ArrayBuffer value, e.g. a step output object holding the PDF instead of its URL.

Common situations: Passing a fetch() Response or {data: ...} object directly; forgetting to await/download the PDF bytes into an ArrayBuffer; template interpolation returning a JSON object.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/ef3298867b865146. Report an issue: GitHub.