paperclipai/paperclip · critical · Error

At least one allowed spreadsheet ID is required.

Error message

At least one allowed spreadsheet ID is required.

What it means

createToolDefinitions normalizes options.allowedSpreadsheetIds (trim + dedupe + filter(Boolean)) and refuses to build any tools if the resulting list is empty. The library treats an empty allowlist as a misconfiguration rather than a valid 'deny all' state, because it would otherwise expose tools that can never succeed.

Source

Thrown at packages/google-sheets-mcp-server/src/tools.ts:144

        return formatTextResponse(await execute(parsed));
      } catch (error) {
        return formatErrorResponse(error, options.secretRedactions ?? []);
      }
    },
  };
}

function assertAllowed(allowedSpreadsheetIds: Set<string>, spreadsheetId: string) {
  if (!allowedSpreadsheetIds.has(spreadsheetId)) {
    throw new Error(`Spreadsheet ${spreadsheetId} is not in the configured allowlist.`);
  }
}

export function createToolDefinitions(options: GoogleSheetsToolOptions): GoogleSheetsToolDefinition[] {
  const allowedSpreadsheetIds = Array.from(new Set(options.allowedSpreadsheetIds.map((id) => id.trim()).filter(Boolean)));
  const allowedSpreadsheetIdSet = new Set(allowedSpreadsheetIds);
  if (allowedSpreadsheetIds.length === 0) {
    throw new Error("At least one allowed spreadsheet ID is required.");
  }

  return [
    makeTool(
      options,
      "list_spreadsheets",
      "List the Google Sheets spreadsheets configured in this connection allowlist.",
      "read",
      z.object({}),
      async () => options.client.listSpreadsheets(allowedSpreadsheetIds),
    ),
    makeTool(
      options,
      "get_spreadsheet_info",
      "Get spreadsheet metadata and sheet tab information for an allowlisted spreadsheet.",
      "read",
      spreadsheetToolSchema,
      async ({ spreadsheetId }) => {

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Set the allowed spreadsheet IDs env var (e.g. GOOGLE_SHEETS_SPREADSHEET_IDS='id1,id2') and confirm it is visible to the server process.
  2. If constructing the config in code, pass at least one non-empty string in allowedSpreadsheetIds.
  3. Print the resolved config at startup to confirm the value is not being stripped by a loader.

Example fix

// before
createToolDefinitions({ allowedSpreadsheetIds: [], client })
// after
createToolDefinitions({ allowedSpreadsheetIds: ['1Bx...'], client })
Defensive patterns

Strategy: validation

Validate before calling

const ids = (process.env.GOOGLE_SHEETS_SPREADSHEET_IDS ?? '').split(',').map(s=>s.trim()).filter(Boolean);
if (ids.length === 0) throw new Error('Set GOOGLE_SHEETS_SPREADSHEET_IDS before starting the server');
createToolDefinitions({ allowedSpreadsheetIds: ids, client });

Prevention

When it happens

Trigger: Starting the google-sheets MCP server with allowedSpreadsheetIds unset, empty, or filled only with whitespace/blank strings; a config loader that silently drops the field on parse failure.

Common situations: Missing GOOGLE_SHEETS_SPREADSHEET_IDS env var in deployment; .env file not loaded in the process running the MCP server; CI secret masking that replaces the value with an empty string.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/e3ad551f44979efe. Report an issue: GitHub.