Skip to content

Error Handling

The MvaTestResult.isError field is the universal signal for pipeline failures. It's true whenever:

  • Zod input validation rejects the arguments
  • Middleware blocks the call (e.g., RBAC rejection)
  • The handler explicitly returns error()
  • The tool or action name is unknown

Testing Unknown Tools

typescript
describe('Error: Unknown Tool', () => {
    it('sets isError for nonexistent tools', async () => {
        const result = await tester.callAction('nonexistent_tool', 'list');

        expect(result.isError).toBe(true);
    });
});

Testing Unknown Actions

typescript
describe('Error: Unknown Action', () => {
    it('sets isError for nonexistent actions', async () => {
        const result = await tester.callAction('db_user', 'nonexistent_action');

        expect(result.isError).toBe(true);
    });
});

Testing Handler-Returned Errors

When a handler explicitly returns error():

typescript
// In your handler:
handler: async () => {
    return error('This operation is temporarily disabled.');
}

Test it:

typescript
describe('Error: Handler Error', () => {
    it('sets isError when handler returns error()', async () => {
        const result = await tester.callAction('system', 'disabled_action');

        expect(result.isError).toBe(true);
        expect(result.data).toContain('temporarily disabled');
    });
});

Empty MVA Layers on Error

When a pipeline error occurs, the MVA layers (systemRules, uiBlocks) should be empty — no partial data leaks:

typescript
describe('Error: Empty MVA Layers', () => {
    it('returns empty systemRules on error', async () => {
        const result = await tester.callAction('db_user', 'find_many', { take: 99999 });

        expect(result.isError).toBe(true);
        expect(result.systemRules).toEqual([]);
    });

    it('returns empty uiBlocks on error', async () => {
        const result = await tester.callAction('db_user', 'find_many', { take: 99999 });

        expect(result.isError).toBe(true);
        expect(result.uiBlocks).toEqual([]);
    });
});

Testing Error Message Content

Assert the error message for debugging and monitoring:

typescript
describe('Error Messages', () => {
    it('middleware error contains "Unauthorized"', async () => {
        const result = await tester.callAction(
            'db_user', 'find_many', { take: 5 },
            { role: 'GUEST' },
        );

        expect(result.isError).toBe(true);
        expect(result.data).toContain('Unauthorized');
    });

    it('handler error contains the specific message', async () => {
        const result = await tester.callAction('system', 'disabled_action');

        expect(result.isError).toBe(true);
        expect(result.data).toContain('temporarily disabled');
    });
});

Error vs Exception

Important distinction: isError: true means the pipeline handled the error gracefully. The FusionTester returned a structured result. This is different from an unhandled exception (which would throw).

typescript
it('validation errors are handled, not thrown', async () => {
    // This does NOT throw — it returns isError: true
    const result = await tester.callAction('db_user', 'find_many', { take: 'invalid' });

    expect(result.isError).toBe(true);
    expect(result.data).toBeDefined(); // error message is in data
});