moeru-ai/airi · error
Source with id ${request.sourceId} not found.
Error message
Source with id ${request.sourceId} not found. What it means
Thrown inside the session.setDisplayMediaRequestHandler callback when desktopCapturer.getSources(request.options) returns no source whose id equals request.sourceId. The handler was registered by screenCapture.setSource; it looks up the previously-enumerated source to feed back into the display-media callback.
Source
Thrown at packages/electron-screen-capture/src/main/index.ts:242
const { timeout } = request
if (typeof timeout === 'number' && (timeout <= 0 || !Number.isFinite(timeout) || Number.isNaN(timeout))) {
throw new Error('timeout must be a positive finite number')
}
await setSourceMutex.acquire()
log.withFields({ windowId, windowTitle: tryWindowTitle(window, windowTitle) }).debug('setSourceMutex acquired')
clearTimeout(setSourceMutexTimeoutHandle)
const handle = nanoid()
setSourceMutexTimeoutHandle = undefined
screenCaptureSourceMutexHandle = handle
try {
session.setDisplayMediaRequestHandler(async (_request, callback) => {
const sources = await desktopCapturer.getSources(request.options)
const source = sources.find(source => source.id === request.sourceId)
if (!source) {
throw new Error(`Source with id ${request.sourceId} not found.`)
}
callback({
video: source,
audio: options?.loopbackWithMute ? LoopbackAudioTypes.LoopbackWithMute : LoopbackAudioTypes.Loopback,
})
})
setSourceMutexTimeoutHandle = setTimeout(() => {
if (screenCaptureSourceMutexHandle !== handle)
return
resetScreenCaptureSource()
setSourceMutex.release()
log
.withFields({ windowId, windowTitle: tryWindowTitle(window, windowTitle) })
.warn(View on GitHub (pinned to 27111382b4)
Solutions
- Re-fetch sources via getSources immediately before calling setSource and use the fresh id.
- Match request.options types to the source type you are selecting (screen vs window).
- Handle the error in the renderer and fall back to letting the user re-pick a source.
- Avoid caching source ids across long periods or across display-configuration changes.
Example fix
// before
invoke(setSource, { sourceId: cachedId, options: { types: ['screen'] } })
// after
const sources = await invoke(getSources, { types: ['screen'] })
const match = sources.find(s => s.id === cachedId) ?? sources[0]
if (!match) throw new Error('no source')
invoke(setSource, { sourceId: match.id, options: { types: ['screen'] } }) Defensive patterns
Strategy: validation
Validate before calling
// Re-fetch and confirm the source id is current before calling setSource
const sources = await invoke(screenCapture.getSources, request.options)
if (!sources.some(s => s.id === request.sourceId)) {
throw new Error('sourceId is stale; pick a fresh source from getSources()')
} Type guard
function isKnownSource(id: string, sources: { id: string }[]): boolean {
return sources.some(s => s.id === id)
} Try / catch
try {
await invoke(screenCapture.setSource, { sourceId, options })
} catch (error) {
if (error instanceof Error && /Source with id .* not found/.test(error.message)) {
// refresh and retry once with a fresh source
const fresh = await invoke(screenCapture.getSources, options)
await invoke(screenCapture.setSource, { sourceId: fresh[0].id, options })
} else throw error
} Prevention
- Never cache source ids longer than the display-configuration lifetime.
- Match request.options.types to the source category you are selecting.
- Refresh the source list right before letting the user pick.
When it happens
Trigger: Renderer calls setSource with a sourceId that is stale (the source list changed between enumeration and selection), belongs to a different session, or is malformed; request.options filters (types/types) exclude the source so it is not returned.
Common situations: Source disconnected between listing and picking (display unplugged, app closed); source list cached too long in the renderer; types filter mismatch (e.g. requesting a 'window' id with types: ['screen']); cross-platform source id format differences.
Related errors
- No active source selected
- Selected source did not provide a live video track
- mutexAcquireTimeout must be a positive finite number
- initScreenCaptureForMain must be called before calling initS
- timeout must be a positive finite number
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/f1a107790320ffc7.
Report an issue: GitHub.