ToolJet/ToolJet · error · QueryError

URL missing

Error message

URL missing

What it means

Thrown by Qdrant getConnection() as a QueryError when sourceOptions.url is falsy. The QdrantClient constructor requires a URL, so the plugin refuses to construct one without it. This fires before any network call and before testConnection's getCollections attempt.

Source

Thrown at marketplace/plugins/qdrant/lib/index.ts:81

    };
  }
  async testConnection(sourceOptions: SourceOptions): Promise<ConnectionTestResult> {
    const qdrant = await this.getConnection(sourceOptions);

    try {
      await qdrant.getCollections();
      return { status: 'ok' };
    } catch (error) {
      console.error('Connection could not be established:', error.message);
      throw new QueryError('Connection could not be established', error?.message, {});
    }
  }

  async getConnection(sourceOptions: SourceOptions): Promise<QdrantClient> {
    const { apiKey, url } = sourceOptions;

    if (!url) {
      throw new QueryError('URL missing', 'No Qdrant URL provided in source options', {});
    }

    return new QdrantClient({
      url,
      apiKey,
    });
  }

  private parseJSON(json?: string): object {
    if (!json) return {};

    return JSON.parse(json);
  }
}

View on GitHub (pinned to 20602a8e10)

Solutions

  1. Set the Qdrant URL in the datasource configuration (e.g. http://localhost:6333 or https://<cluster>.cloud.qdrant.io) and save.
  2. Confirm the option key is exactly 'url' on the backend side.
  3. If calling programmatically, ensure sourceOptions contains { url: string, apiKey?: string }.

Example fix

// before
const sourceOptions = { apiKey: 'xxx' }; // url missing

// after
const sourceOptions = { url: 'http://localhost:6333', apiKey: 'xxx' };
Defensive patterns

Strategy: validation

Validate before calling

function assertQdrantSource(opts: { url?: string; apiKey?: string }) {
  if (!opts?.url || !opts.url.trim()) throw new Error('Qdrant url is required in source options.');
}

Type guard

const hasQdrantUrl = (o: unknown): o is { url: string; apiKey?: string } =>
  typeof o === 'object' && o !== null && typeof (o as any).url === 'string' && (o as any).url.trim() !== '';

Try / catch

try { return await plugin.getConnection(sourceOptions); }
catch (e) { if (/URL missing|No Qdrant URL/.test(e?.message ?? '')) { /* prompt to set url */ } throw e; }

Prevention

When it happens

Trigger: getConnection() destructures { apiKey, url } from sourceOptions and finds url undefined/empty. The datasource was saved without a URL, or the URL field key sent to the backend does not match 'url'.

Common situations: Datasource URL field left blank; field key mismatch after a schema change; environment/migration issue where sourceOptions was not hydrated; copy of a datasource config that dropped the URL.

Related errors


AI-assisted analysis of ToolJet/ToolJet@20602a8e10 (2026-08-13). Data as JSON: /api/errors/67e1b8fb4e5bd919. Report an issue: GitHub.