Skip to main content

Troubleshooting

Common errors and their solutions when working with farseer-client.

Dimension connections not filtering correctly

When filtering Arquero tables loaded from Farseer dimension tables, connections to other tables are arrays, not single values.

// WRONG - connections are arrays, not strings
const electronics = table.filter(d => d?.['Category'] === 'Electronics');
// Returns empty or incorrect results

// CORRECT - use [0] to access the first element
const electronics = table.filter(d => d?.['Category'][0] === 'Electronics');

Why: Dimension table connections (foreign keys) are stored as arrays. Always access with [0]:

// Filtering
table.filter(d => d?.['Category'][0] === 'Electronics');

// Deriving
table.derive({
CategoryName: d => d?.['Category'][0] || 'Unknown',
SupplierName: d => d?.['Supplier'][0] || 'N/A'
});

// Grouping
table.groupby(d => d?.['Category'][0]).count();

Unsupported expression construct: ChainExpression

Error: Unsupported expression construct: ChainExpression
at visit (/node_modules/arquero/dist/arquero.node.js:2907:7)

Cause: Arquero's expression parser doesn't support optional chaining (?.), nullish coalescing (??), and some other modern JavaScript syntax.

// WRONG - optional chaining not supported
const filtered = table.filter((d: any) => d?.value !== null && d?.value !== 0);

Fix: Wrap the expression in aq.escape():

import * as aq from 'arquero';

// CORRECT - use aq.escape()
const filtered = table.filter(aq.escape((d: any) => d?.value !== null && d?.value !== 0));

// Also for derive
const transformed = table.derive({
Years: aq.escape((d: any) => d.Years?.substring(1)),
Months: aq.escape((d: any) => d.Months?.substring(1))
});

When to use aq.escape():

  • Optional chaining: d?.value
  • Nullish coalescing: d.value ?? 0
  • Complex logic that Arquero's parser rejects

When NOT to use aq.escape():

  • Simple expressions: d => d.value > 0
  • After .objects() (plain JavaScript arrays don't need it)

TAG_IDs are incorrect/outdated

Symptom: Import fails because hardcoded tag IDs no longer match.

Fix:

  1. Use named lookups instead of hardcoded IDs when possible:
    // Preferred - use names
    const revenue = await client.getVariable('Revenue');

    // Avoid - hardcoded IDs can become stale
    const revenue = TAG_IDS.VARIABLES.REVENUE;
  2. If hardcoded IDs are needed, verify them in Farseer UI and update tagIds.ts.

Import job commit fails

Common causes:

  1. Rows not visible before commitcommit() automatically flushes remaining rows, but if you're debugging (breakpoint or commented-out commit), call flushRows() explicitly to see all rows in the UI:

    await importJob.addRows(rows);
    await importJob.flushRows(); // Makes all rows visible for inspection
    // await importJob.commit(); // Commented out for debugging
  2. Invalid dimension members - Validate data before import:

    const products = await client.getDimensionMembersForTable('Product');
    const validNames = products.map(p => p.name);
    const validRows = rows.filter(r => validNames.includes(r[0]));
  3. Missing dimension in columns - Ensure all required dimensions are specified in the import job columns.


Connection/Authentication errors

  1. Check environment variables:

    echo $TENANT_ID
    echo $FARSEER_API_KEY
    echo $FARSEER_URL
  2. Verify manual configuration:

    const client = new FarseerClient('tenant-id', 'api-key', 'https://app.farseer.io');
  3. Check API key permissions in the Farseer UI under Settings > API Keys.


Debugging Tips

Check existing dimension members

await client.initTagMap();
const products = await client.getDimensionMembersForTable('Product');
products.forEach(p => console.log(p.name));

Dry run model.load

const result = await client.model.load({
model: { tables: [...] },
options: {
dryRun: true // Preview changes without applying
}
});

Inspect response errors

main().catch(async (error: any) => {
if (error && typeof error.text === 'function') {
console.error(await error.text());
} else {
console.error(error);
}
process.exit(1);
});