Skip to main content

Troubleshooting Common Issues

Troubleshooting Common Issues

Issue: Rate Limiting

Symptoms: 429 Too Many Requests responses

Solution: Implement exponential backoff and respect retry-after headers

const fetchWithBackoff = async (url, options, maxRetries = 3) => {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);

if (response.status !== 429) {
return response;
}

const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
}

throw new Error('Max retries exceeded');
};

Issue: Feature Not Supported (HTTP 501)

Symptoms: HTTP 501 Not Implemented response

Solution: Check server capabilities via GET /info before calling optional features. History, update, and streaming subscriptions are optional.

const info = await fetch('https://api.i3x.dev/v1/info').then(r => r.json());

if (!info.result.capabilities.query.history) {
console.warn('This server does not support historical queries');
// Fall back to current values only
}

Issue: Partial Results (HTTP 206)

Symptoms: HTTP 206 Partial Content response from value or history queries

Explanation: The server reached its internal depth limit before completing the requested maxDepth. This is not an error — the response contains valid data, just not as deep as requested.

Solution: Process partial results normally, optionally retry with a smaller maxDepth:

const response = await fetch('https://api.i3x.dev/v1/objects/value', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ elementIds, maxDepth: 5 })
});

if (response.status === 206) {
console.warn('Partial results returned — server depth limit reached');
}

const data = await response.json();
// data.results contains the partial results — still process them

Issue: Large Data Set Handling

Solution: Use time-bounded queries and subscriptions for streaming

// For historical data, use time-bounded queries
const getHistoryInChunks = async (token, elementIds, startTime, endTime) => {
const response = await fetch('https://api.i3x.dev/v1/objects/history', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
elementIds: elementIds,
startTime: startTime,
endTime: endTime,
maxDepth: 1
})
});

const data = await response.json();
return data.results;
};

// For real-time streaming, use subscriptions
// Note: subscription management uses flat POST endpoints — subscriptionId goes in the body
const streamObjectData = async (token, elementIds, callback) => {
// Create subscription
const createRes = await fetch('https://api.i3x.dev/v1/subscriptions', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ displayName: 'Stream Monitor' })
});
const createData = await createRes.json();
const subscriptionId = createData.result.subscriptionId;

// Register objects to monitor (subscriptionId in body)
await fetch('https://api.i3x.dev/v1/subscriptions/register', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ subscriptionId, elementIds, maxDepth: 1 })
});

// Stream via SSE (subscriptionId in body)
const streamRes = await fetch('https://api.i3x.dev/v1/subscriptions/stream', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ subscriptionId })
});

const reader = streamRes.body.getReader();
const decoder = new TextDecoder();

const read = async () => {
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value);
for (const line of text.split('\n')) {
if (line.startsWith('data: ')) {
callback(JSON.parse(line.slice(6)));
}
}
}
};

read();
return { subscriptionId };
};

Issue: Unexpected success: false in Bulk Results

Symptoms: Top-level success is false even though some items succeeded

Explanation: In bulk operations, the top-level success is false if any item fails. Check individual items in results:

const data = await response.json();

// Don't just check data.success — inspect each result
const succeeded = data.results.filter(r => r.success);
const failed = data.results.filter(r => !r.success);

if (failed.length > 0) {
console.warn('Some items failed:', failed.map(r => ({
elementId: r.elementId,
error: r.error
})));
}

// Process successful results
succeeded.forEach(r => processValue(r.elementId, r.result));