windmill-labs/windmill · error · Error

Unresolved inline script references: ${unresolvedRefs.join('

Error message

Unresolved inline script references: ${unresolvedRefs.join(', ')}

What it means

assertResolvedInlineScripts runs when restoring flow modules from an inline-script editing session. During the session, module code may contain placeholder references to inline scripts that the session promised to materialize. If findUnresolvedInlineScriptRefs still finds placeholders in the final modules, restore is aborted with this error listing the unresolved refs.

Source

Thrown at frontend/src/lib/components/copilot/chat/flow/helperUtils.ts:357

function restoreFlowModule(
	module: FlowModule,
	inlineScriptSession: InlineScriptSession,
	emptyInlineScriptModuleIds: Set<string>
): FlowModule {
	const [restoredModule] = inlineScriptSession.restoreInlineScriptReferences([module])
	replaceNewInlineScriptRefsWithEmptyCode([restoredModule], emptyInlineScriptModuleIds)
	assertResolvedInlineScripts([restoredModule], inlineScriptSession)
	return restoredModule
}

function assertResolvedInlineScripts(
	modules: FlowModule[],
	inlineScriptSession: InlineScriptSession
): void {
	const unresolvedRefs = inlineScriptSession.findUnresolvedInlineScriptRefs(modules)
	if (unresolvedRefs.length > 0) {
		throw new Error(`Unresolved inline script references: ${unresolvedRefs.join(', ')}`)
	}
}

export function replaceNewInlineScriptRefsWithEmptyCode(
	modules: FlowModule[],
	emptyInlineScriptModuleIds: Set<string>
): void {
	function replaceInlineScriptRefWithEmptyCode(ownerId: string, content: string): string {
		const match = content.match(/^inline_script\.(.+)$/)
		if (!match || match[1] !== ownerId) {
			return content
		}

		emptyInlineScriptModuleIds.add(ownerId)
		return ''
	}

	forEachFlowModule(modules, (module) => {

View on GitHub (pinned to e474e8803c)

Solutions

  1. Complete the session: call set_flow_module_code with the final code for every placeholder module before restoring.
  2. Replace remaining placeholder refs with real script paths or inline code in the modules.
  3. If the module is not needed, remove it from the modules array before restore.
  4. Check the listed refs in the error against the modules to find which module still carries the placeholder.

Example fix

// before
restoreFlowModules(modulesWithPlaceholders, session) // throws
// after
setFlowModuleCode(session, moduleId, finalCode)
restoreFlowModules(modulesWithPlaceholders, session)
Defensive patterns

Strategy: try-catch

Validate before calling

const unresolved = inlineScriptSession.findUnresolvedInlineScriptRefs(modules)
if (unresolved.length > 0) {
  throw new Error(`resolve before restore: ${unresolved.join(', ')}`)
}

Type guard

null

Try / catch

try {
  restoreFlowModules(modules, session)
} catch (e) {
  if (e.message.startsWith('Unresolved inline script references')) {
    for (const ref of e.message.slice('Unresolved inline script references: '.length).split(', ')) {
      await setFlowModuleCode(session, refToModuleId(ref), placeholderBody)
    }
    restoreFlowModules(modules, session)
  }
}

Prevention

When it happens

Trigger: Calling restoreFlowModules/restoreFlowModule while modules still contain inline-script placeholder refs that were never given code in the session — e.g. a session created a placeholder module but set_flow_module_code was never called for it before restore.

Common situations: The AI agent's restore step ran before all code-fill steps completed; a module was added with a placeholder mid-session and then the flow was restored without finishing it; an error in an earlier tool call skipped the code-fill step.

Related errors


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