ComposioHQ/composio · error · ValidationError

Custom tool slugs are not supported in preload.tools: ${cust

Error message

Custom tool slugs are not supported in preload.tools: ${customPreloadSlugs.join(', ')}. Set preload: true on the SDK custom tool or custom toolkit definition instead.

What it means

The SDK rejects session preload configurations that name custom tools directly in preload.tools. Custom tools must opt into preloading via `preload: true` on their own definition, because the preload list only accepts backend tool slugs.

Source

Thrown at ts/packages/core/src/models/CustomTool.ts:631

): void {
  if (!preloadTools || preloadTools === PRELOAD_TOOLS_ALL) {
    return;
  }

  const customPreloadSlugs = preloadTools.filter(slug => {
    const normalized = slug.toUpperCase();
    return (
      // Top-level preload.tools is only for Composio-managed tool slugs.
      // Custom tools use `preload: true` on their SDK definitions instead.
      normalized.startsWith(LOCAL_TOOL_PREFIX) ||
      customToolsMap?.byOriginalSlug.has(normalized) ||
      customToolsMap?.ambiguousOriginalSlugs?.has(normalized) ||
      customToolsMap?.byFinalSlug.has(normalized)
    );
  });

  if (customPreloadSlugs.length) {
    throw new ValidationError(
      `Custom tool slugs are not supported in preload.tools: ${customPreloadSlugs.join(
        ', '
      )}. Set preload: true on the SDK custom tool or custom toolkit definition instead.`
    );
  }
}

/**
 * Resolve custom tools that the SDK should expose directly from session.tools().
 *
 * @internal
 */
export function getPreloadedCustomToolSlugs(
  customToolsMap: CustomToolsMap | undefined,
  defaultPreload = false
): string[] {
  if (!customToolsMap) {
    return [];

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Remove the custom tool slug from preload.tools and set `preload: true` on the custom tool definition
  2. For a custom toolkit, set preload: true on the toolkit definition instead
  3. Verify remaining preload.tools entries are ordinary (non-custom) tool slugs

Example fix

// before
await composio.sessions.create({ preload: { tools: ['my_custom_tool'] } });
// after
const tool = defineTool({ slug: 'my_custom_tool', preload: true, /* ... */ });
await composio.sessions.create({});
Defensive patterns

Strategy: validation

Validate before calling

const customSlugs = new Set([...customTools.map(t => t.slug.toUpperCase()), ...customToolsMap?.ambiguousOriginalSlugs ?? []]);
const bad = (preload.tools ?? []).filter(s => customSlugs.has(s.toUpperCase()));
if (bad.length) throw new Error(`Custom slugs in preload.tools: ${bad.join(', ')}`);

Type guard

const preloadIsSafe = (preloadTools: string[], customSlugs: Set<string>): boolean =>
  preloadTools.every(s => !customSlugs.has(s.toUpperCase()));

Try / catch

try { await composio.sessions.create(cfg); } catch (e) { if (e instanceof ValidationError && e.message.includes('preload.tools')) { cfg.preload.tools = []; delete cfg.preload; /* set preload on tool instead */ } }

Prevention

When it happens

Trigger: Passing a session config whose preload.tools array contains a slug that resolves to an SDK custom tool or custom toolkit tool (checked against the custom tools map, including ambiguous original slugs). Raised from assertNoCustomToolSlugsInPreload during prepareInlineCustomTools.

Common situations: Migrating a config that preloaded a standard tool and swapping in a custom tool slug; assuming preload.tools accepts anything in the tools list; referencing a custom tool by original slug that also exists in the map.

Related errors


AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28). Data as JSON: /api/errors/055ccedc6a8a5f70. Report an issue: GitHub.