evernote-common-errors
SKILL.md
Evernote Common Errors
Overview
Comprehensive guide to diagnosing and resolving Evernote API errors, including EDAMUserException, EDAMSystemException, and EDAMNotFoundException.
Prerequisites
- Basic Evernote SDK setup
- Understanding of Evernote data model
Error Types
Evernote uses three main exception types:
| Exception | When Thrown |
|---|---|
EDAMUserException |
Client error - invalid input, permissions |
EDAMSystemException |
Server error - rate limits, maintenance |
EDAMNotFoundException |
Resource not found - invalid GUID |
EDAMUserException Errors
BAD_DATA_FORMAT
Cause: Invalid ENML content or malformed data
// Error
{
errorCode: 1, // BAD_DATA_FORMAT
parameter: 'Note.content'
}
// Common causes and fixes:
// 1. Missing XML declaration
// Wrong:
'<en-note><p>Hello</p></en-note>'
// Correct:
`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
<en-note><p>Hello</p></en-note>`
// 2. Forbidden HTML elements
// Wrong: contains <script>
`<en-note><script>alert('hi')</script></en-note>`
// Correct: remove scripts
`<en-note><p>Content only</p></en-note>`
// 3. Unclosed tags
// Wrong:
'<en-note><p>Hello<br></en-note>'
// Correct:
'<en-note><p>Hello</p><br/></en-note>'
Fix: Validate ENML before sending:
function validateENML(content) {
const errors = [];
// Required declarations
if (!content.includes('<?xml version="1.0"')) {
errors.push('Missing XML declaration');
}
if (!content.includes('<!DOCTYPE en-note')) {
errors.push('Missing DOCTYPE');
}
if (!content.includes('<en-note>')) {
errors.push('Missing <en-note> root element');
}
// Forbidden elements
const forbidden = [
/<script/i, /<form/i, /<input/i, /<button/i,
/<iframe/i, /<object/i, /<embed/i, /<applet/i
];
forbidden.forEach(pattern => {
if (pattern.test(content)) {
errors.push(`Forbidden element: ${pattern.source}`);
}
});
// Forbidden attributes
if (/\s(class|id|onclick|onload|onerror)=/i.test(content)) {
errors.push('Forbidden attributes (class, id, event handlers)');
}
return { valid: errors.length === 0, errors };
}
DATA_REQUIRED
Cause: Missing required field
// Error
{
errorCode: 2, // DATA_REQUIRED
parameter: 'Note.title'
}
// Fix: Ensure required fields are set
const note = new Evernote.Types.Note();
note.title = 'Required Title'; // Cannot be null or empty
note.content = validENMLContent; // Cannot be null
PERMISSION_DENIED
Cause: API key lacks required permissions
// Error
{
errorCode: 3, // PERMISSION_DENIED
parameter: 'NoteStore.shareNote'
}
// Causes:
// 1. API key doesn't have sharing permission
// 2. Trying to access business features without business API key
// 3. Accessing notes in shared notebooks without permission
// Fix: Request appropriate permissions when creating API key
// See: https://dev.evernote.com/doc/articles/permissions.php
INVALID_AUTH
Cause: Invalid or expired authentication token
// Error
{
errorCode: 4, // INVALID_AUTH
parameter: 'authenticationToken'
}
// Fix: Check token validity
async function checkTokenValidity(client) {
try {
const userStore = client.getUserStore();
await userStore.getUser();
return { valid: true };
} catch (error) {
if (error.errorCode === 4) {
return {
valid: false,
reason: 'Token expired or revoked',
action: 'Re-authenticate via OAuth'
};
}
throw error;
}
}
AUTH_EXPIRED
Cause: Token has passed expiration date
// Error
{
errorCode: 5, // AUTH_EXPIRED
parameter: 'authenticationToken'
}
// Tokens expire after 1 year by default
// Users can set shorter: 1 day, 1 week, 1 month
// Fix: Store and check expiration
function isTokenExpired(expirationTimestamp) {
return Date.now() > expirationTimestamp;
}
// When authenticating, save edam_expires:
// results.edam_expires contains expiration timestamp
LIMIT_REACHED
Cause: Account limits exceeded
// Error
{
errorCode: 6, // LIMIT_REACHED
parameter: 'Notebook.name'
}
// Account limits:
// - 250 notebooks max
// - 100,000 tags max
// - 100,000 notes max (business accounts)
// - Upload limits per month
// Fix: Check limits before creating
async function canCreateNotebook(noteStore) {
const notebooks = await noteStore.listNotebooks();
return notebooks.length < 250;
}
QUOTA_REACHED
Cause: Monthly upload quota exceeded
// Error
{
errorCode: 7, // QUOTA_REACHED
parameter: 'Note.content'
}
// Quotas vary by account type:
// - Basic: 60 MB/month
// - Premium: 10 GB/month
// - Business: 20 GB/month (per user)
// Check remaining quota
async function getRemainingQuota(userStore) {
const user = await userStore.getUser();
const accounting = user.accounting;
return {
uploadLimit: accounting.uploadLimit,
uploadLimitEnd: new Date(accounting.uploadLimitEnd),
uploaded: accounting.uploaded,
remaining: accounting.uploadLimit - accounting.uploaded
};
}
EDAMSystemException Errors
RATE_LIMIT_REACHED
Cause: Too many API calls per hour
// Error
{
errorCode: 19, // RATE_LIMIT_REACHED
rateLimitDuration: 300 // seconds until reset
}
// Fix: Implement exponential backoff
async function withRateLimitRetry(operation, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
if (error.errorCode === 19 && error.rateLimitDuration) {
console.log(`Rate limited. Waiting ${error.rateLimitDuration}s...`);
await sleep(error.rateLimitDuration * 1000);
continue;
}
throw error;
}
}
throw new Error('Max retries exceeded');
}
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
SYSTEM_MAINTENANCE
Cause: Evernote service is under maintenance
// Error
{
errorCode: 1, // UNKNOWN (with message about maintenance)
message: 'Service temporarily unavailable'
}
// Fix: Retry with backoff
async function withMaintenanceRetry(operation) {
const delays = [1000, 5000, 15000, 60000]; // Progressive delays
for (const delay of delays) {
try {
return await operation();
} catch (error) {
if (error.message?.includes('temporarily unavailable')) {
console.log(`Service maintenance. Retrying in ${delay / 1000}s...`);
await sleep(delay);
continue;
}
throw error;
}
}
throw new Error('Service unavailable - maintenance ongoing');
}
EDAMNotFoundException Errors
Cause: Referenced resource doesn't exist
// Error
{
identifier: 'Note.guid',
key: '12345678-abcd-1234-efgh-invalid00000'
}
// Common scenarios:
// 1. Note was deleted
// 2. Note is in trash
// 3. Invalid GUID format
// 4. Note belongs to different user
// Fix: Handle gracefully
async function safeGetNote(noteStore, guid) {
try {
return await noteStore.getNote(guid, true, false, false, false);
} catch (error) {
if (error.identifier === 'Note.guid') {
console.log(`Note not found: ${guid}`);
return null;
}
throw error;
}
}
Error Handling Service
// services/error-handler.js
const Evernote = require('evernote');
class EvernoteErrorHandler {
static handle(error) {
// EDAMUserException
if (error.errorCode !== undefined && error.parameter !== undefined) {
return this.handleUserException(error);
}
// EDAMSystemException
if (error.errorCode !== undefined && error.rateLimitDuration !== undefined) {
return this.handleSystemException(error);
}
// EDAMNotFoundException
if (error.identifier !== undefined) {
return this.handleNotFoundException(error);
}
// Unknown error
return {
type: 'UNKNOWN',
message: error.message || 'Unknown Evernote error',
recoverable: false,
original: error
};
}
static handleUserException(error) {
const codes = {
1: { name: 'BAD_DATA_FORMAT', action: 'Validate input data format' },
2: { name: 'DATA_REQUIRED', action: 'Provide required field' },
3: { name: 'PERMISSION_DENIED', action: 'Check API key permissions' },
4: { name: 'INVALID_AUTH', action: 'Re-authenticate user' },
5: { name: 'AUTH_EXPIRED', action: 'Token expired, re-authenticate' },
6: { name: 'LIMIT_REACHED', action: 'Account limit exceeded' },
7: { name: 'QUOTA_REACHED', action: 'Upload quota exceeded' }
};
const info = codes[error.errorCode] || { name: 'UNKNOWN', action: 'Check documentation' };
return {
type: 'USER_EXCEPTION',
code: error.errorCode,
name: info.name,
parameter: error.parameter,
action: info.action,
recoverable: [4, 5].includes(error.errorCode),
original: error
};
}
static handleSystemException(error) {
return {
type: 'SYSTEM_EXCEPTION',
code: error.errorCode,
rateLimitDuration: error.rateLimitDuration,
action: `Wait ${error.rateLimitDuration} seconds before retrying`,
recoverable: true,
original: error
};
}
static handleNotFoundException(error) {
return {
type: 'NOT_FOUND',
identifier: error.identifier,
key: error.key,
action: 'Resource does not exist or was deleted',
recoverable: false,
original: error
};
}
}
module.exports = EvernoteErrorHandler;
Usage Example
const ErrorHandler = require('./services/error-handler');
async function createNoteSafely(noteStore, note) {
try {
return await noteStore.createNote(note);
} catch (error) {
const handled = ErrorHandler.handle(error);
console.error('Evernote error:', handled.name || handled.type);
console.error('Parameter:', handled.parameter || handled.identifier);
console.error('Action:', handled.action);
if (handled.recoverable) {
console.log('Error is recoverable');
if (handled.rateLimitDuration) {
await sleep(handled.rateLimitDuration * 1000);
return noteStore.createNote(note);
}
}
throw error;
}
}
Output
- Understanding of all Evernote exception types
- Error code reference with solutions
- Reusable error handling service
- Rate limit retry implementation
Quick Reference
| Code | Exception | Cause | Fix |
|---|---|---|---|
| 1 | UserException | Bad data format | Validate ENML |
| 2 | UserException | Missing required field | Add required field |
| 3 | UserException | Permission denied | Check API key |
| 4 | UserException | Invalid auth | Re-authenticate |
| 5 | UserException | Auth expired | Refresh token |
| 6 | UserException | Limit reached | Check account limits |
| 7 | UserException | Quota reached | Check upload quota |
| 19 | SystemException | Rate limit | Wait rateLimitDuration |
| - | NotFoundException | GUID not found | Verify resource exists |
Resources
Next Steps
For debugging tools and techniques, see evernote-debug-bundle.
Weekly Installs
13
Repository
jeremylongshore…s-skillsGitHub Stars
1.6K
First Seen
Feb 18, 2026
Security Audits
Installed on
mcpjam13
claude-code13
replit13
junie13
windsurf13
zencoder13