Error Handling Overview
All SDK methods (execute(), embed(), retrieve()) throw errors when something goes wrong. In most cases, the SDK automatically shows a Notice in the Obsidian UI with the error message.
Even though the SDK displays errors in the UI, you should still handle errors in your plugin code to prevent crashes and provide better user experiences.
Error Types
The SDK can throw several types of errors:
- Provider errors: Issues connecting to or authenticating with AI providers
- Abort errors: When operations are cancelled via
AbortController
- Validation errors: Invalid parameters or missing required fields
- Network errors: Connection timeouts or network failures
execute() Error Handling
Since SDK 1.5.0, execute() returns a Promise<string> that rejects on error.
Basic Error Handling
try {
const result = await aiProviders.execute({
provider: aiProviders.providers[0],
prompt: "What is the capital of Great Britain?",
onProgress: (chunk, full) => {
console.log(full);
}
});
console.log('Success:', result);
} catch (error) {
// Error is also shown as a Notice in Obsidian
console.error('Execution failed:', error);
}
Handling Abort Errors
When using AbortController, the error message will be exactly "Aborted". Check for this specific string to distinguish user cancellations from other errors.
const abortController = new AbortController();
try {
const result = await aiProviders.execute({
provider: aiProviders.providers[0],
prompt: "Stream something...",
abortController,
onProgress: (_chunk, text) => {
console.log(text);
// Abort after 50 characters
if (text.length > 50) {
abortController.abort();
}
}
});
console.log('Completed:', result);
} catch (e) {
if ((e as Error).message === 'Aborted') {
console.log('Generation aborted intentionally');
} else {
console.error('Unexpected error:', e);
}
}
try {
const result = await aiProviders.execute({
provider: aiProviders.providers[0],
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "What is the capital of Great Britain?" }
],
onProgress: (_chunk, text) => console.log(text)
});
console.log('Result:', result);
} catch (error) {
console.error('Chat execution failed:', error);
// Handle provider-specific errors
if (error instanceof Error) {
if (error.message.includes('API key')) {
console.error('Authentication error - check API key');
} else if (error.message.includes('timeout')) {
console.error('Request timed out');
}
}
}
embed() Error Handling
The embed() method throws errors for invalid input, provider issues, or aborted operations.
Basic Error Handling
try {
const embeddings = await aiProviders.embed({
provider: aiProviders.providers[0],
input: "What is the capital of Great Britain?",
});
console.log('Embeddings:', embeddings);
} catch (error) {
// Error is also shown as a Notice
console.error('Embedding failed:', error);
}
Progress Tracking with Error Handling
try {
const embeddings = await aiProviders.embed({
provider: aiProviders.providers[0],
input: ["Text 1", "Text 2", "Text 3"],
onProgress: (processedChunks) => {
console.log(`Processed: ${processedChunks.length} chunks`);
}
});
console.log('All embeddings generated:', embeddings.length);
} catch (error) {
console.error('Embedding generation failed:', error);
}
Abort Handling for Embeddings
const abortController = new AbortController();
try {
const embeddings = await aiProviders.embed({
provider: aiProviders.providers[0],
input: ["Text 1", "Text 2", "Text 3"],
abortController,
onProgress: (processedChunks) => {
if (processedChunks.length >= 2) {
abortController.abort();
}
}
});
} catch (error) {
if ((error as Error).message === 'Aborted') {
console.log('Embedding aborted by user');
} else {
console.error('Embedding error:', error);
}
}
retrieve() Error Handling
The retrieve() method can throw errors related to document processing, embeddings, or search operations.
Basic Error Handling
try {
const results = await aiProviders.retrieve({
query: "machine learning algorithms",
documents: documents,
embeddingProvider: aiProviders.providers[0]
});
console.log('Found results:', results.length);
} catch (error) {
// Handle retrieval errors (e.g., provider issues, invalid documents)
console.error('Retrieval failed:', error);
}
Progress Tracking with Error Handling
try {
const results = await aiProviders.retrieve({
query: "search query",
documents: documents,
embeddingProvider: aiProviders.providers[0],
onProgress: (progress) => {
const percentage = (progress.processedChunks.length / progress.totalChunks) * 100;
console.log(`Progress: ${percentage.toFixed(1)}%`);
}
});
console.log('Search complete:', results.length, 'results');
} catch (error) {
console.error('Search failed:', error);
}
Abort Handling for Retrieval
const abortController = new AbortController();
try {
const results = await aiProviders.retrieve({
query: "search query",
documents: largeDocumentSet,
embeddingProvider: aiProviders.providers[0],
abortController,
onProgress: (progress) => {
// Cancel if processing takes too long
if (progress.processedChunks.length > 1000) {
abortController.abort();
}
}
});
} catch (error) {
if ((error as Error).message === 'Aborted') {
console.log('Search cancelled');
} else {
console.error('Search error:', error);
}
}
fetchModels() Error Handling
try {
const models = await aiProviders.fetchModels({
provider: aiProviders.providers[0],
abortController: new AbortController()
});
console.log('Available models:', models);
} catch (error) {
console.error('Failed to fetch models:', error);
}
Provider-Specific Errors
Different providers may return different error messages. Common patterns:
try {
const result = await aiProviders.execute({
provider: provider,
prompt: "Test prompt"
});
} catch (error) {
if (error instanceof Error) {
// OpenAI/OpenRouter API errors
if (error.message.includes('401') || error.message.includes('API key')) {
console.error('Authentication failed - check API key');
}
// Ollama connection errors
else if (error.message.includes('ECONNREFUSED')) {
console.error('Cannot connect to Ollama - is it running?');
}
// Rate limiting
else if (error.message.includes('429') || error.message.includes('rate limit')) {
console.error('Rate limit exceeded - wait before retrying');
}
// Model not found
else if (error.message.includes('404') || error.message.includes('model')) {
console.error('Model not found or not available');
}
}
}
Best Practices
- Always use try/catch: Wrap all SDK method calls in try/catch blocks
- Check abort errors: Use
error.message === 'Aborted' to detect user cancellations
- Log for debugging: Log errors to console even though they appear in Notices
- Provide feedback: Show custom UI feedback based on error types
- Handle async properly: Use
await or .catch() on all promise-returning methods
- Don’t suppress errors: Let users know when something fails