Mintplex-Labs/anything-llm · error · Error
Not a valid URL.
Error message
Not a valid URL.
What it means
connect() calls client.describeIndex(PINECONE_INDEX) and throws when status.ready is falsy. Pinecone reports ready=true only once an index is fully provisioned and servable; a freshly created index (especially serverless or pod-based) spends seconds to minutes in an initializing state. This is a startup race between index creation and first use, not an authentication problem.
Solutions
- Wait 30-60 seconds (serverless) or a few minutes (pods) after index creation, then retry the operation — readiness is transient.
- Check the index state directly: Pinecone console, or `curl -H "Api-Key: $PINECONE_API_KEY" https://api.pinecone.io/indexes/$PINECONE_INDEX` and confirm status.state is 'Ready'.
- Verify PINECONE_INDEX points at the intended, fully provisioned index in the same project as the API key.
- Wrap first-use connect() in a bounded retry-with-backoff loop that only retries on 'not ready' and rethrows everything else.
Example fix
// before
const conn = await pinecone.connect(); // throws during provisioning
// after - retry only the transient 'not ready' case
async function connectWhenReady(db, tries = 12) {
for (let i = 0; i < tries; i++) {
try {
return await db.connect();
} catch (e) {
if (!/not ready/i.test(e.message)) throw e;
await new Promise((r) => setTimeout(r, 5_000));
}
}
throw new Error('Pinecone index still not ready after retry window');
} Defensive patterns
Strategy: retry
Validate before calling
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: process.env.PINECONE_API_KEY });
const desc = await pc.describeIndex(process.env.PINECONE_INDEX).catch(() => null);
if (!desc?.status?.ready) {
// index still provisioning — do not call connect()/embed yet
throw new Error(`Index not ready (state: ${desc?.status?.state ?? 'unknown'})`);
} Type guard
async function isPineconeIndexReady(pc, indexName) {
const d = await pc.describeIndex(indexName).catch(() => null);
return d?.status?.ready === true;
} Try / catch
const MAX_TRIES = 10;
for (let i = 0; i < MAX_TRIES; i++) {
try {
return await pineconeDB.connect();
} catch (e) {
if (!/not ready/i.test(e.message)) throw e; // only the transient case retries
await new Promise((r) => setTimeout(r, 5_000 * (i + 1)));
}
}
throw new Error('Pinecone index never became ready'); Prevention
- Create Pinecone indexes ahead of deployment, not inline with the first embed.
- Poll describeIndex(...).status.ready at startup and gate ingestion on it.
- Treat status.state values other than 'Ready' as a deployment blocker surfaced in health checks.
- Never auto-retry non-transient Pinecone errors with the same loop — match on the message first.
When it happens
Trigger: Creating a Pinecone index and immediately embedding documents or calling /api/ext/vectors/heartbeat; embedding right after recreating an index with the same name; hitting an index that Pinecone lists in a non-Ready lifecycle state (initializing, failed, paused); first embed after a fresh deploy pointed at a brand-new index.
Common situations: Infrastructure scripts that create-then-load without waiting; index recreated during migration/restore; Pinecone control-plane slowness during provisioning; a wrong PINECONE_INDEX name that resolves to a different, not-yet-ready index in the account.
Related errors
- Failed to get YouTube video transcription
- FFMPEG conversion failed
- [Gitea Loader]: Rate limit hit for
- [Gitlab Loader]: Rate limit hit fetching
- [Gitlab Loader]: Rate limit hit for
AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18).
Data as JSON: /api/errors/df1557b30c44bc1d.
Report an issue: GitHub.
Appendix: source
Thrown at collector/extensions/index.js:131
data: {
title: null,
author: null,
},
});
}
return;
}
);
app.post(
"/ext/website-depth",
[verifyPayloadIntegrity],
async function (request, response) {
try {
const websiteDepth = require("../utils/extensions/WebsiteDepth");
const { url, depth = 1, maxLinks = 20 } = reqBody(request);
const validatedUrl = validateURL(url);
if (!validURL(validatedUrl)) throw new Error("Not a valid URL.");
const scrapedData = await websiteDepth(validatedUrl, depth, maxLinks);
response.status(200).json({ success: true, data: scrapedData });
} catch (e) {
console.error(e);
response.status(400).json({ success: false, reason: e.message });
}
return;
}
);
app.post(
"/ext/confluence",
[verifyPayloadIntegrity, setDataSigner],
async function (request, response) {
try {
const { loadConfluence } = require("../utils/extensions/Confluence");
const { success, reason, data } = await loadConfluence(
reqBody(request),View on GitHub (pinned to 3aec848f28)