Skip to content

🕵️‍♂️ fix: Handle 404 errors on agent queries for favorites#11587

Open
ethanlaj wants to merge 1 commit intodanny-avila:devfrom
ethanlaj:fix-agent-delete-logic
Open

🕵️‍♂️ fix: Handle 404 errors on agent queries for favorites#11587
ethanlaj wants to merge 1 commit intodanny-avila:devfrom
ethanlaj:fix-agent-delete-logic

Conversation

@ethanlaj
Copy link
Contributor

Pull Request Template

Summary

Danny has already handled agent deletion updating user favorites (in #11466), however, does not handle the following cases:

  1. User clicks "favorite" on a different agent on the frontend - the frontend has the deleted agent in the favorites state and re-sends it up in the favorite POST request. This causes the agent to get re-added into the user's favorites unintentionally.
  2. User loses access to an existing agent (through a permission revoke by another user)
  3. An external process removes/deletes an agent

When an agent favorite doesn't exist, queries for the agent fail with a 404 error, and cause an infinite skeleton load for favorites + agent marketplace

Change Type

  • Bug fix (non-breaking change which fixes an issue)

Testing

Deleted an agent, favorited a different agent, refreshed page, loading skeleton of favorites no longer showing.

Test Configuration:

Checklist

Please delete any irrelevant options.

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • I have commented in any complex areas of my code
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective or that my feature works
  • Local unit tests pass with my changes
  • Any changes dependent on mine have been merged and published in downstream modules.

@ethanlaj ethanlaj force-pushed the fix-agent-delete-logic branch from d1c5c86 to 3491734 Compare January 31, 2026 22:34
@danny-avila danny-avila changed the base branch from dev-staging to dev February 4, 2026 09:12
@danny-avila danny-avila requested a review from Copilot February 4, 2026 09:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request fixes 404 errors that occur when agent favorites reference deleted or inaccessible agents, which previously caused an infinite skeleton loading state in the favorites list and agent marketplace.

Changes:

  • Added a new AgentQueryResult discriminated type to handle both successful and failed agent queries
  • Modified the query function in FavoritesList.tsx to catch 404 errors and return {found: false} instead of throwing
  • Updated the combinedAgentsMap logic to filter out agents where found is false
  • Added comprehensive unit tests for the new error handling logic

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
client/src/common/agents-types.ts Defines new AgentQueryResult type to represent query outcomes for missing/deleted agents
client/src/components/Nav/Favorites/FavoritesList.tsx Implements 404 error handling in agent queries and filters out unfound agents from the combined map
client/src/components/Nav/Favorites/tests/FavoritesList.spec.tsx Adds unit tests for the query result type behavior and combinedAgentsMap filtering logic

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

} from 'librechat-data-provider';
import type { OptionWithIcon, ExtendedFile } from './types';

export type AgentQueryResult = { found: boolean; agent?: Agent };
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AgentQueryResult type allows agent to be optional even when found is true, which isn't type-safe. Consider using a discriminated union type instead:

export type AgentQueryResult = 
  | { found: true; agent: Agent }
  | { found: false };

This would eliminate the need for non-null assertions (!) in FavoritesList.tsx line 219 and provide better type safety.

Suggested change
export type AgentQueryResult = { found: boolean; agent?: Agent };
export type AgentQueryResult =
| { found: true; agent: Agent }
| { found: false };

Copilot uses AI. Check for mistakes.
Comment on lines +132 to +192
describe('AgentQueryResult type behavior', () => {
it('should handle found agent result correctly', async () => {
const mockAgent: t.Agent = {
id: 'agent-123',
name: 'Test Agent',
author: 'test-author',
} as t.Agent;

(dataService.getAgentById as jest.Mock).mockResolvedValueOnce(mockAgent);

const result = await dataService.getAgentById({ agent_id: 'agent-123' });

// Simulate the query function logic
const queryResult: AgentQueryResult = { found: true, agent: result };

expect(queryResult.found).toBe(true);
expect(queryResult.agent).toEqual(mockAgent);
});

it('should handle not found agent result correctly', async () => {
const error = { response: { status: 404 } };
(dataService.getAgentById as jest.Mock).mockRejectedValueOnce(error);

// Simulate the query function logic from FavoritesList
let queryResult: AgentQueryResult | undefined;
try {
await dataService.getAgentById({ agent_id: 'deleted-agent' });
} catch (err) {
if (err && typeof err === 'object' && 'response' in err) {
const axiosError = err as { response?: { status?: number } };
if (axiosError.response?.status === 404) {
queryResult = { found: false };
}
}
}

expect(queryResult).toEqual({ found: false });
});

it('should rethrow non-404 errors', async () => {
const error = { response: { status: 500 }, message: 'Server error' };
(dataService.getAgentById as jest.Mock).mockRejectedValueOnce(error);

// Simulate the query function logic from FavoritesList
let caughtError;
try {
await dataService.getAgentById({ agent_id: 'agent-123' });
} catch (err) {
if (err && typeof err === 'object' && 'response' in err) {
const axiosError = err as { response?: { status?: number } };
if (axiosError.response?.status === 404) {
// Would return { found: false }, but this is a 500
} else {
caughtError = err;
}
}
}

expect(caughtError).toEqual(error);
});
});
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests in the "AgentQueryResult type behavior" describe block (lines 132-192) test the logic in isolation but don't actually test the component's integration with the useQueries hook. Consider adding a test that renders the FavoritesList component with favorites containing missing agent IDs and verifies that:

  1. The component doesn't show infinite loading skeleton
  2. The missing agents are correctly excluded from the rendered favorites
  3. Valid agents are still rendered correctly

This would better validate the bug fix described in the PR.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant