Skip to content

Troubleshooting Guide

Fresh Solutions for common Notion API issues.

Quick Diagnostic Flowchart

Most Common Issues

1. "Object not found" Error

Symptoms:

  • 404 error when accessing pages/databases
  • API returns object_not_found code

Causes & Solutions:

CauseSolution
Page not shared with integrationOpen page → ... menu → Add connections → Select your integration
Wrong ID formatEnsure ID is correct (32 or 36 characters)
Page deleted/archivedCheck trash, restore if needed
ID copied incorrectlyRe-copy from Notion URL

Debug Script:

javascript
async function debugAccess(id) {
  console.log(`Testing access to: ${id}`);

  try {
    // Try as page
    const page = await notion.pages.retrieve({ page_id: id });
    console.log('✅ Accessible as page:', page.url);
    return { type: 'page', data: page };
  } catch (e) {
    console.log('❌ Not a page or no access');
  }

  try {
    // Try as database
    const db = await notion.databases.retrieve({ database_id: id });
    console.log('✅ Accessible as database:', db.title[0]?.plain_text);
    return { type: 'database', data: db };
  } catch (e) {
    console.log('❌ Not a database or no access');
  }

  console.log('\n⚠️ Cannot access resource. Please:');
  console.log('1. Verify the ID is correct');
  console.log('2. Share the page/database with your integration');

  return null;
}

2. Authentication Failures

Symptoms:

  • 401 Unauthorized errors
  • "API token is invalid" message

Checklist:

  • [ ] API key starts with secret_
  • [ ] No extra whitespace in key
  • [ ] Key is for correct workspace
  • [ ] Key hasn't been regenerated
  • [ ] Environment variable is loaded

Debug:

javascript
const apiKey = process.env.NOTION_API_KEY;

console.log('Key loaded:', !!apiKey);
console.log('Key length:', apiKey?.length);
console.log('Starts with secret_:', apiKey?.startsWith('secret_'));
console.log('Has whitespace:', apiKey !== apiKey?.trim());

// Test authentication
try {
  const response = await notion.users.me({});
  console.log('✅ Authenticated as:', response.name);
} catch (error) {
  console.log('❌ Auth failed:', error.message);
}

3. Property Validation Errors

Symptoms:

  • 400 Bad Request
  • "body.properties.X failed validation"

Common Mistakes:

javascript
// ❌ Wrong: Plain string for title
properties: {
  Name: 'My Title'
}

// ✅ Correct: Proper title structure
properties: {
  Name: {
    title: [{ text: { content: 'My Title' } }]
  }
}
javascript
// ❌ Wrong: Wrong property name (case-sensitive)
properties: {
  status: { select: { name: 'Done' } }  // lowercase 's'
}

// ✅ Correct: Exact property name
properties: {
  Status: { select: { name: 'Done' } }  // uppercase 'S'
}
javascript
// ❌ Wrong: Select option doesn't exist
properties: {
  Status: { select: { name: 'Finished' } }  // Not in options
}

// ✅ Correct: Use existing option name
properties: {
  Status: { select: { name: 'Done' } }  // Must match exactly
}

Verify Property Names:

javascript
async function getPropertyNames(databaseId) {
  const db = await notion.databases.retrieve({ database_id: databaseId });

  console.log('Properties:');
  for (const [name, config] of Object.entries(db.properties)) {
    console.log(`  "${name}" - type: ${config.type}`);

    if (config.type === 'select' || config.type === 'multi_select') {
      const options = config[config.type].options;
      console.log('    Options:', options.map(o => o.name).join(', '));
    }
  }
}

4. Rate Limiting

Symptoms:

  • 429 Too Many Requests
  • Requests failing in batches
  • Intermittent failures

Solutions:

javascript
// Simple delay between requests
async function safeRequest(fn) {
  const result = await fn();
  await new Promise(r => setTimeout(r, 350)); // 350ms delay
  return result;
}

// Process items with throttling
async function processItems(items, operation) {
  const results = [];

  for (const item of items) {
    const result = await safeRequest(() => operation(item));
    results.push(result);
  }

  return results;
}

5. Empty Query Results

Symptoms:

  • Query returns empty results array
  • Filter doesn't match expected items

Debug:

javascript
async function debugQuery(databaseId, filter) {
  // First, query without filter
  const allResults = await notion.databases.query({
    database_id: databaseId,
    page_size: 5
  });

  console.log('Total pages (sample):', allResults.results.length);

  if (allResults.results.length > 0) {
    const sample = allResults.results[0];
    console.log('\nSample page properties:');

    for (const [name, value] of Object.entries(sample.properties)) {
      console.log(`  ${name}:`, JSON.stringify(value).slice(0, 100));
    }
  }

  // Now try with filter
  const filtered = await notion.databases.query({
    database_id: databaseId,
    filter
  });

  console.log('\nFiltered results:', filtered.results.length);
  console.log('Filter used:', JSON.stringify(filter, null, 2));
}

Common Filter Issues:

javascript
// ❌ Wrong: Using 'text' instead of specific type
filter: {
  property: 'Name',
  text: { contains: 'test' }  // Wrong for title property
}

// ✅ Correct: Use 'title' for title properties
filter: {
  property: 'Name',
  title: { contains: 'test' }
}
javascript
// ❌ Wrong: Using 'text' for rich_text
filter: {
  property: 'Description',
  text: { contains: 'test' }  // Should be 'rich_text'
}

// ✅ Correct
filter: {
  property: 'Description',
  rich_text: { contains: 'test' }
}

6. Blocks Not Appearing

Symptoms:

  • Blocks created but not visible
  • Content missing from page

Causes:

CauseSolution
Wrong page IDVerify ID is for page, not database
Blocks in wrong formatCheck block structure
Rate limit during creationAdd delays, verify each block
Nested too deepMax 2 levels when creating

Verify Blocks:

javascript
async function verifyBlocks(pageId) {
  const response = await notion.blocks.children.list({
    block_id: pageId,
    page_size: 100
  });

  console.log('Blocks in page:', response.results.length);

  for (const block of response.results) {
    console.log(`  ${block.type}:`, block.id);

    if (block.has_children) {
      const children = await notion.blocks.children.list({
        block_id: block.id
      });
      console.log(`    Children: ${children.results.length}`);
    }
  }
}

7. Webhook Not Receiving Events

Symptoms:

  • Webhook registered but no events
  • Verification challenge not received

Checklist:

  • [ ] HTTPS endpoint (not HTTP)
  • [ ] Endpoint publicly accessible
  • [ ] Correct response to verification challenge
  • [ ] Firewall allows Notion IPs
  • [ ] Response within 30 seconds

Test Endpoint:

javascript
// Test endpoint locally
const express = require('express');
const app = express();

app.use(express.raw({ type: 'application/json' }));

app.post('/webhook', (req, res) => {
  const event = JSON.parse(req.body.toString());

  console.log('Received event:', event.type);

  if (event.type === 'verification') {
    console.log('Verification challenge:', event.challenge);
    return res.json({ challenge: event.challenge });
  }

  res.status(200).send('OK');
});

app.listen(3000, () => console.log('Listening on 3000'));

8. SDK Type Errors

Symptoms:

  • TypeScript errors with SDK
  • Unexpected undefined values

Common Patterns:

javascript
// Safe property access
const title = page.properties.Name?.title?.[0]?.plain_text || 'Untitled';
const status = page.properties.Status?.select?.name || null;
const tags = page.properties.Tags?.multi_select?.map(t => t.name) || [];

// Type checking
function extractPageData(page) {
  const props = page.properties;

  return {
    // Title - always check array
    title: props.Name?.title?.[0]?.plain_text ?? '',

    // Select - check for null
    status: props.Status?.select?.name ?? null,

    // Multi-select - default to empty array
    tags: props.Tags?.multi_select?.map(t => t.name) ?? [],

    // Number - default to 0 or null
    priority: props.Priority?.number ?? 0,

    // Date - check for date object
    dueDate: props['Due Date']?.date?.start ?? null,

    // Checkbox - default to false
    done: props.Done?.checkbox ?? false,

    // People - extract names
    assignees: props.Assignee?.people?.map(p => p.name) ?? []
  };
}

Debug Environment Setup

javascript
// debug.js - Comprehensive debug script
require('dotenv').config();
const { Client, isNotionClientError } = require('@notionhq/client');

async function runDiagnostics() {
  console.log('🔍 Notion API Diagnostics\n');

  // 1. Check environment
  console.log('1. Environment Variables');
  console.log('   NOTION_API_KEY:', process.env.NOTION_API_KEY ? '✅ Set' : '❌ Missing');
  console.log('   NOTION_DATABASE_ID:', process.env.NOTION_DATABASE_ID ? '✅ Set' : '❌ Missing');

  if (!process.env.NOTION_API_KEY) {
    console.log('\n❌ Cannot continue without API key');
    return;
  }

  const notion = new Client({ auth: process.env.NOTION_API_KEY });

  // 2. Test authentication
  console.log('\n2. Authentication');
  try {
    const me = await notion.users.me({});
    console.log('   ✅ Authenticated as:', me.name);
    console.log('   Bot ID:', me.id);
  } catch (error) {
    console.log('   ❌ Auth failed:', error.message);
    return;
  }

  // 3. Test database access
  if (process.env.NOTION_DATABASE_ID) {
    console.log('\n3. Database Access');
    try {
      const db = await notion.databases.retrieve({
        database_id: process.env.NOTION_DATABASE_ID
      });
      console.log('   ✅ Database:', db.title[0]?.plain_text);
      console.log('   Properties:', Object.keys(db.properties).join(', '));
    } catch (error) {
      console.log('   ❌ Database access failed:', error.message);
    }
  }

  // 4. Test search
  console.log('\n4. Search Capability');
  try {
    const search = await notion.search({ query: '', page_size: 1 });
    console.log('   ✅ Can search, found:', search.results.length, 'items');
  } catch (error) {
    console.log('   ❌ Search failed:', error.message);
  }

  console.log('\n✅ Diagnostics complete');
}

runDiagnostics().catch(console.error);

Getting Help

If issues persist:

  1. Check Notion Status: https://status.notion.so/
  2. Review API Changelog: https://developers.notion.com/changelog
  3. Search Notion Community: https://www.notion.so/community
  4. Include in Bug Reports:
    • Request ID (from error response)
    • API version used
    • Full error message
    • Minimal reproduction code

See Also

Built with VitePress | Powered by Claude AI