fix(docker): enhance error handling and user feedback for Docker service unavailability
This commit is contained in:
@@ -604,9 +604,21 @@ export default function ProxyHostForm({ host, onSubmit, onCancel }: ProxyHostFor
|
||||
))}
|
||||
</select>
|
||||
{dockerError && connectionSource !== 'custom' && (
|
||||
<p className="text-xs text-red-400 mt-1">
|
||||
Failed to connect: {(dockerError as Error).message}
|
||||
</p>
|
||||
<div className="mt-2 p-3 bg-red-500/10 border border-red-500/30 rounded-lg">
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertTriangle className="w-4 h-4 text-red-400 flex-shrink-0 mt-0.5" />
|
||||
<div className="text-xs text-red-300">
|
||||
<p className="font-semibold mb-1">Docker Connection Failed</p>
|
||||
<p className="text-red-400/90 mb-2">
|
||||
{(dockerError as Error).message}
|
||||
</p>
|
||||
<p className="text-gray-400">
|
||||
<strong>Troubleshooting:</strong> Ensure Docker is running and the socket is accessible.
|
||||
If running in a container, mount <code className="text-xs bg-gray-800 px-1 py-0.5 rounded">/var/run/docker.sock</code>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -123,6 +123,35 @@ describe('useDocker', () => {
|
||||
expect(result.current.containers).toEqual([]);
|
||||
});
|
||||
|
||||
it('extracts details from 503 service unavailable error', async () => {
|
||||
const mockError = {
|
||||
response: {
|
||||
status: 503,
|
||||
data: {
|
||||
error: 'Docker daemon unavailable',
|
||||
details: 'Cannot connect to Docker. Please ensure Docker is running and the socket is accessible (e.g., /var/run/docker.sock is mounted).'
|
||||
}
|
||||
}
|
||||
};
|
||||
vi.mocked(dockerApi.listContainers).mockRejectedValue(mockError);
|
||||
|
||||
const { result } = renderHook(() => useDocker('local'), {
|
||||
wrapper: createWrapper(),
|
||||
});
|
||||
|
||||
await waitFor(
|
||||
() => {
|
||||
expect(result.current.isLoading).toBe(false);
|
||||
},
|
||||
{ timeout: 3000 }
|
||||
);
|
||||
|
||||
// Verify error message includes the details
|
||||
expect(result.current.error).toBeTruthy();
|
||||
const errorMessage = (result.current.error as Error)?.message;
|
||||
expect(errorMessage).toContain('Docker is running');
|
||||
});
|
||||
|
||||
it('provides refetch function', async () => {
|
||||
vi.mocked(dockerApi.listContainers).mockResolvedValue(mockContainers);
|
||||
|
||||
|
||||
@@ -9,7 +9,19 @@ export function useDocker(host?: string | null, serverId?: string | null) {
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey: ['docker-containers', host, serverId],
|
||||
queryFn: () => dockerApi.listContainers(host || undefined, serverId || undefined),
|
||||
queryFn: async () => {
|
||||
try {
|
||||
return await dockerApi.listContainers(host || undefined, serverId || undefined)
|
||||
} catch (err: any) {
|
||||
// Extract helpful error message from response
|
||||
if (err.response?.status === 503) {
|
||||
const details = err.response?.data?.details
|
||||
const message = details || 'Docker service unavailable. Check that Docker is running.'
|
||||
throw new Error(message)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
},
|
||||
enabled: Boolean(host) || Boolean(serverId),
|
||||
retry: 1, // Don't retry too much if docker is not available
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user