Documentation Index
Fetch the complete documentation index at: https://docs.cocobase.buzz/llms.txt
Use this file to discover all available pages before exploring further.
Troubleshooting
Solutions to common problems and debugging techniques to get you back on track quickly.
Authentication Issues
Issue: “API key is invalid”
Symptoms:
DioException: 401 Unauthorized - Invalid API key
Error: API request failed (status: 401)
Solutions:
-
Verify API Key is Correct
Flutter
JavaScript
Python
Go
// Check your API key is correct
final config = CocobaseConfig(
apiKey: "YOUR_API_KEY_HERE", // Copy from dashboard
);
const config = {
apiKey: "YOUR_API_KEY_HERE", // Copy from dashboard
};
# Cloud Functions
# Verify API key in dashboard settings
config := cocobase.Config{
APIKey: "YOUR_API_KEY_HERE", // Copy from dashboard
}
-
Check API Key Format
- API keys are typically 32-64 characters
- Should be alphanumeric
- Don’t add quotes or extra spaces
-
Verify API Key is Active
- Go to CocoBase Dashboard
- Check if the API key is enabled
- Check expiration date
-
Use Environment Variables
// Better approach
const apiKey = String.fromEnvironment('COCOBASE_API_KEY');
final config = CocobaseConfig(apiKey: apiKey);
Issue: “User session expired”
Symptoms:
DioException: 401 Unauthorized during request
Session token invalid or expired
Solutions:
-
Implement Token Refresh
Future<T> withAutomaticRefresh<T>(
Future<T> Function() request,
) async {
try {
return await request();
} on DioException catch (e) {
if (e.response?.statusCode == 401) {
// Token expired - ask user to login again
await db.logout();
throw Exception('Please login again');
}
rethrow;
}
}
-
Check Token Storage
// Verify token is saved correctly
final isAuth = await db.isAuthenticated();
print('Authenticated: $isAuth');
-
Clear Cache and Retry
// Force fresh login
await db.logout();
final result = await db.login(
email: 'user@example.com',
password: 'password',
);
Issue: “Email already registered”
Symptoms:
DioException: 409 Conflict - Email already in use
Solutions:
-
Use Different Email
try {
await db.register(
email: 'newemail@example.com',
password: 'SecurePassword123!',
);
} on DioException catch (e) {
if (e.response?.statusCode == 409) {
print('Email already registered - try another');
}
}
-
Implement Password Reset Flow
Instead of creating a new account, direct users to password reset.
Connection Problems
Issue: “Network timeout”
Symptoms:
DioException: Connection timeout after 30000ms
SocketException: Failed to connect
Solutions:
-
Check Internet Connection
import 'package:connectivity_plus/connectivity_plus.dart';
Future<bool> hasInternet() async {
final connectivity = await Connectivity().checkConnectivity();
return connectivity != ConnectivityResult.none;
}
-
Implement Retry Logic
Future<T> withRetry<T>(
Future<T> Function() request, {
int maxAttempts = 3,
}) async {
for (int i = 0; i < maxAttempts; i++) {
try {
return await request();
} catch (e) {
if (i == maxAttempts - 1) rethrow;
await Future.delayed(Duration(seconds: 2 << i)); // Exponential backoff
}
}
throw Exception('Max retries exceeded');
}
// Use it
final books = await withRetry(() => db.listDocuments<Book>("books"));
-
Increase Timeout (if needed)
const config = {
apiKey: "YOUR_KEY",
timeout: 60000, // 60 seconds
};
Issue: “Certificate verification failed”
Symptoms:
HandshakeException: Handshake error in client
Certificate verification failed
Solutions:
-
Ensure Using HTTPS
final config = CocobaseConfig(
apiKey: 'YOUR_KEY',
baseUrl: 'https://api.cocobase.cc', // Must be HTTPS
);
-
Check Device Date/Time
- SSL certificates are time-sensitive
- Ensure device date/time is correct
-
Update Dependencies
flutter pub upgrade
npm update
Query Issues
Issue: “No results when expecting data”
Common Causes & Solutions:
-
Field Name Typo
// Wrong - typo in field name
final docs = await db.listDocuments("books", filters: {
'titulo': 'Flutter', // Typo!
});
// Correct
final docs = await db.listDocuments("books", filters: {
'title': 'Flutter',
});
-
Case Sensitivity
Field names are case-sensitive! Match the exact case from your database schema.
-
Operator Missing
// Wrong - looking for exact price
final docs = await db.listDocuments("books", filters: {
'price': 29.99, // Exact match only
});
// Correct - use operators
final docs = await db.listDocuments("books", filters: {
'price__gte': 20,
'price__lte': 50,
});
-
Wrong Data Type
// Wrong - comparing string to number
final docs = await db.listDocuments("books", filters: {
'price': '29.99', // String!
});
// Correct - use correct type
final docs = await db.listDocuments("books", filters: {
'price': 29.99, // Number
});
Issue: “QueryBuilder not building correct query”
Debug with .build():
final query = QueryBuilder()
.where('status', 'published')
.whereGreaterThan('price', 20)
.limit(10);
// Output: status=published&price__gt=20&limit=10
// Plain filter alternative:
const filters = {
status: 'published',
price__gt: 20,
limit: 10
};
Common Mistakes:
// Wrong - not using offset
final docs = await db.listDocuments("books", filters: {
'limit': 20,
'limit': 40, // Second limit overwrites first!
});
// Correct - use offset for pages
final page1 = await db.listDocuments("books", filters: {
'limit': 20,
'offset': 0,
});
final page2 = await db.listDocuments("books", filters: {
'limit': 20,
'offset': 20,
});
Type Conversion Errors
Issue: “type ‘_InternalLinkedHashMap<String, dynamic>’ is not a subtype”
Cause: Type mismatch in fromJson() method
// Wrong - assuming wrong type
factory Book.fromJson(Map<String, dynamic> json) {
return Book(
price: json['price'] as String, // API returns number!
);
}
// Correct - match actual type
factory Book.fromJson(Map<String, dynamic> json) {
return Book(
price: (json['price'] as num).toDouble(), // Convert properly
);
}
Fix Strategy:
// 1. Check what type the API actually returns
final doc = await db.getDocument("books", "doc-id");
print(doc.data.runtimeType); // Check actual type
print(doc.data); // Print the data
// 2. Update your fromJson to match
factory Book.fromJson(Map<String, dynamic> json) {
return Book(
price: _parsePrice(json['price']), // Use helper
);
}
static double _parsePrice(dynamic value) {
if (value is num) return value.toDouble();
if (value is String) return double.parse(value);
return 0.0;
}
Issue: “NoSuchMethodError: The method ‘fromJson’ was called on null”
Cause: Converter not registered
// Wrong - forgot to register
final books = await db.listDocuments<Book>("books");
// Correct - register first
CocobaseConverters.register<Book>(Book.fromJson);
final books = await db.listDocuments<Book>("books");
// Or pass explicit converter
final books = await db.listDocuments<Book>(
"books",
converter: Book.fromJson,
);
Issue: “null value error when accessing optional field”
Cause: Not handling null values
// Wrong - force unwrap optional
final subtitle = json['subtitle'] as String; // Crashes if null!
// Correct - handle null
final subtitle = json['subtitle'] as String?; // Nullable
// Or with default
final subtitle = (json['subtitle'] as String?) ?? 'No subtitle';
Real-Time Connection Problems
Issue: “WebSocket connection fails”
Solutions:
-
Verify Collection Exists
// Check collection exists before watching
try {
final collection = await db.getCollection('books');
await db.watchCollection('books', (event) {
print('Event: ${event.type}');
});
} catch (e) {
print('Collection error: $e');
}
-
Check WebSocket is Enabled
Most BaaS platforms enable WebSocket by default. Verify in your project settings.
-
Use Correct Filters
// Correct - use filters parameter
await db.watchCollection('books', callback,
filters: {'status': 'published'},
);
Issue: “Real-time updates stopped”
Solutions:
-
Reconnect on Disconnect
class RobustWatcher {
Future<void> watch(String collection) async {
try {
await db.watchCollection(collection, (event) {
// Handle event
});
} catch (e) {
print('Watch failed: $e');
// Reconnect after delay
await Future.delayed(Duration(seconds: 5));
await watch(collection); // Retry
}
}
}
-
Check Network State
Future<void> watchWithNetworkCheck(String collection) async {
if (await hasInternet()) {
await db.watchCollection(collection, (event) {
// Handle event
});
} else {
print('No internet connection');
}
}
File Upload Errors
Issue: “File upload fails”
Common Causes:
-
File Too Large
// Check file size before upload
final file = File(path);
final fileSize = await file.length();
final maxSize = 10 * 1024 * 1024; // 10MB
if (fileSize > maxSize) {
throw Exception('File too large (max 10MB)');
}
-
Invalid File Type
// Validate file extension
final allowedExtensions = ['.jpg', '.jpeg', '.png', '.pdf'];
final extension = path.substring(path.lastIndexOf('.'));
if (!allowedExtensions.contains(extension.toLowerCase())) {
throw Exception('Invalid file type');
}
-
Network Timeout
// Increase timeout for large files
final config = CocobaseConfig(
apiKey: apiKey,
timeout: Duration(minutes: 5), // 5 minute timeout
);
Issue: “App is slow when loading many documents”
Solutions:
-
Use Pagination
// Wrong - load everything at once
final docs = await db.listDocuments("books");
// Correct - paginate
final docs = await db.listDocuments("books", filters: {
'limit': 50,
'offset': 0,
});
-
Select Only Needed Fields
// Wrong - fetch all fields
final docs = await db.listDocuments("books");
// Correct - select specific fields
final docs = await db.listDocuments("books",
queryBuilder: QueryBuilder()
.select('id')
.select('title')
.select('price'),
);
-
Use Indexes
// Wrong - querying non-indexed field
final docs = await db.listDocuments("books", filters: {
'description__contains': 'flutter', // Slow!
});
// Correct - query indexed field
final docs = await db.listDocuments("books", filters: {
'status': 'published', // Fast if indexed
});
Issue: “Memory usage increases over time”
Solutions:
-
Clear Collections
class SafeCollectionWatch {
Future<void> watch(String collection) async {
final eventBuffer = <WatchEvent>[];
await db.watchCollection(collection, (event) {
eventBuffer.add(event);
// Process and clear buffer periodically
if (eventBuffer.length >= 100) {
_processBatch(eventBuffer);
eventBuffer.clear();
}
});
}
}
-
Dispose Resources
@override
void dispose() {
db.closeConnection(); // Important!
super.dispose();
}
Cloud Functions Issues
Issue: “Function execution timeout”
Causes:
- Heavy computation
- Database query taking too long
- External API call delay
Solutions:
-
Optimize Database Queries
# Bad - no limit
posts = db.query("posts")
# Good - with limit
posts = db.query("posts", limit=100)
-
Use Indexes
# Query indexed fields for faster results
posts = db.query("posts",
status="published", # Indexed
author_id=user_id, # Indexed
limit=50
)
-
Implement Caching
def main():
# Check cache first
cache_key = f"stats_{datetime.now().date()}"
cached = db.find_one("cache", key=cache_key)
if cached:
return cached['data']
# Calculate stats (expensive)
stats = calculate_stats()
# Store in cache
db.create_document("cache", {
"key": cache_key,
"data": stats,
"expires_at": (datetime.now() + timedelta(hours=24)).isoformat()
})
return stats
Issue: “Function returns unexpected errors”
Debug Steps:
-
Enable Logging
def main():
try:
print(f"Request method: {req.method}")
print(f"Request data: {req.json()}")
result = process_data()
print(f"Result: {result}")
return {"result": result}
except Exception as e:
print(f"Error: {str(e)}")
import traceback
traceback.print_exc()
return {"error": str(e)}, 500
-
Validate Input
def main():
user_id = req.get("user_id")
if not user_id:
return {"error": "user_id is required"}, 400
# Continue processing
-
Test Locally
Create a test script with sample data to debug your function logic.
Debugging Tips
Enable Debug Logging
import 'package:dio/dio.dart';
final dio = Dio();
dio.interceptors.add(
LogInterceptor(
requestBody: true,
responseBody: true,
requestHeader: true,
responseHeader: true,
),
);
// Enable axios logging
axios.interceptors.request.use(request => {
console.log('Starting Request', request);
return request;
});
axios.interceptors.response.use(response => {
console.log('Response:', response);
return response;
});
// Enable HTTP request logging
client := cocobase.NewClient(cocobase.Config{
APIKey: apiKey,
Debug: true, // Enable debug mode
})
Print Document Details
final doc = await db.getDocument("books", "doc-id");
print('ID: ${doc.id}');
print('Collection: ${doc.collection}');
print('Data: ${doc.data}');
print('Data type: ${doc.data.runtimeType}');
print('Created: ${doc.createdAt}');
print('Updated: ${doc.updatedAt}');
Check Query String
final query = QueryBuilder()
.where('status', 'published')
.whereGreaterThan('price', 20);
print('Query: ${query.build()}');
Test in Isolation
Create minimal reproduction cases:
void main() async {
final db = Cocobase(CocobaseConfig(apiKey: 'test-key'));
// Minimal test case
try {
final result = await db.listDocuments('books');
print('Success: ${result.length} books');
} catch (e) {
print('Error: $e');
}
}
Common Error Messages
”Collection not found”
Solution: Create the collection first or check spelling.
// Create collection
await db.createCollection(Collection(name: 'books'));
// Then query
final books = await db.listDocuments('books');
”Invalid filter operator”
Solution: Check operator syntax.
// Wrong
'price_greater': 20
// Correct
'price__gt': 20 // Double underscore
”Document not found”
Solution: Verify document ID exists.
// Check if document exists first
final exists = await db.documentExists('books', docId);
if (exists) {
final doc = await db.getDocument('books', docId);
}
”Validation failed”
Solution: Check required fields and data types.
// Ensure all required fields are present
final data = {
'title': 'Book Title', // Required
'author': 'Author Name', // Required
'price': 29.99, // Required, must be number
'isbn': '978-0-123456-78-9', // Optional
};
await db.createDocument('books', data);
FAQ
Q: How do I reset my API key?
A: Go to your CocoBase Dashboard → Settings → API Keys → Generate New Key. Update your application with the new key before revoking the old one.
Q: Why are my queries slow?
A: Common causes:
- Missing indexes on queried fields
- Fetching too many documents (use pagination)
- Populating too many relationships
- Not using query operators efficiently
See Query Optimization for solutions.
Q: How do I handle rate limiting?
A: Implement retry logic with exponential backoff. See Rate Limiting for examples.
Q: Can I use raw SQL queries?
A: In cloud functions, you can use db.execute_raw_query() but be careful with SQL injection. Always use parameterized queries.
Q: How do I backup my data?
A: Use the export functionality or create a cloud function that periodically exports data to cloud storage.
def backup_data():
# Get all documents
docs = db.query("collection", limit=10000)
# Save to file or cloud storage
import json
backup = json.dumps(docs["data"])
return {"backed_up": len(docs["data"])}
Q: Why isn’t my converter working?
A: Make sure you:
- Registered the converter:
CocobaseConverters.register<Book>(Book.fromJson)
- Used the correct type parameter:
db.listDocuments<Book>("books")
- Defined
fromJson() factory method correctly
Getting Help
Resources
-
Documentation
-
Community
-
Contact Support
- Email: support@cocobase.cc
- Dashboard: Help button in top-right corner
- Live Chat: Available during business hours
Reporting Issues
When reporting a bug, include:
// 1. SDK version
print('CocoBase SDK version: 1.0.0');
// 2. Platform version
// Dart --version
// Flutter --version
// Node --version
// 3. Minimal reproduction
final db = Cocobase(CocobaseConfig(apiKey: 'test-key'));
final books = await db.listDocuments("books");
// 4. Full error message and stack trace
// (Copy from console)
// 5. Expected vs actual behavior
// Expected: List of 10 books
// Actual: Empty array
Before Asking for Help
- Check this troubleshooting guide
- Review the documentation
- Search existing GitHub issues
- Try a minimal reproduction
- Check your API key and network connection
Error Code Reference
| Code | Meaning | Common Cause |
|---|
| 400 | Bad Request | Invalid data format, missing required fields |
| 401 | Unauthorized | Invalid API key, expired session |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource doesn’t exist |
| 409 | Conflict | Duplicate entry (e.g., email already exists) |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-side error |
| 502 | Bad Gateway | Temporary server issue |
| 503 | Service Unavailable | Server maintenance or overload |
Next Steps