This error occurs when a Prisma Pulse subscription is terminated unexpectedly, often due to connection issues, resource limits, or manual cancellation. Understanding subscription lifecycle management is key to preventing this error.
The P6003 error indicates that an active Prisma Pulse subscription has been cancelled before the stream completed naturally. Prisma Pulse enables real-time database change notifications through subscriptions to specific tables or queries. When a subscription is cancelled, it means the stream of database events has been interrupted. This can happen for several reasons: network disconnections between your application and Prisma's infrastructure, exceeding subscription limits (initially 10 active subscriptions per table), manual cancellation via the stop() method, or infrastructure issues on either the client or server side. When this error occurs, your application will no longer receive real-time updates for the affected subscription. Prisma Pulse currently has limited automatic reconnection capabilities, so applications need to handle reconnection logic explicitly.
Check how many active subscriptions you have per table. Prisma Pulse initially limits you to 10 active subscriptions per table.
// Track active subscriptions
const activeSubscriptions = new Map<string, any>();
const subscription = await prisma.user.subscribe({
create: { after: true }
});
activeSubscriptions.set('user-subscription-1', subscription);
// Check count before creating new ones
if (activeSubscriptions.size >= 10) {
console.warn('Subscription limit approaching');
}Always stop subscriptions you no longer need to free up slots.
Ensure subscriptions are properly stopped when no longer needed to avoid resource exhaustion.
let subscription: any = null;
async function startSubscription() {
subscription = await prisma.user.subscribe({
create: { after: true }
});
for await (const event of subscription) {
console.log('User created:', event);
}
}
// Cleanup on shutdown
process.on('SIGTERM', async () => {
if (subscription) {
subscription.stop();
}
await prisma.$disconnect();
});This prevents zombie subscriptions that count against your limit.
Prisma Pulse doesn't automatically reconnect on network failures. Implement retry logic to handle P6003 errors.
async function createResilientSubscription(maxRetries = 3) {
let retries = 0;
while (retries < maxRetries) {
try {
const subscription = await prisma.user.subscribe({
create: { after: true }
});
for await (const event of subscription) {
console.log('Event received:', event);
}
} catch (error: any) {
if (error.code === 'P6003') {
retries++;
console.log(`Subscription cancelled, retry ${retries}/${maxRetries}`);
await new Promise(resolve => setTimeout(resolve, 1000 * retries));
continue;
}
throw error;
}
}
}This provides automatic recovery from transient connection issues.
Add monitoring to detect when subscriptions are cancelled and alert accordingly.
interface SubscriptionHealth {
id: string;
startTime: Date;
lastEventTime: Date | null;
status: 'active' | 'cancelled' | 'error';
}
const healthMap = new Map<string, SubscriptionHealth>();
async function monitoredSubscription(id: string) {
healthMap.set(id, {
id,
startTime: new Date(),
lastEventTime: null,
status: 'active'
});
try {
const subscription = await prisma.user.subscribe({
create: { after: true }
});
for await (const event of subscription) {
const health = healthMap.get(id)!;
health.lastEventTime = new Date();
health.status = 'active';
}
} catch (error: any) {
const health = healthMap.get(id);
if (health) {
health.status = error.code === 'P6003' ? 'cancelled' : 'error';
}
throw error;
}
}This helps identify patterns in subscription failures.
If you need guaranteed event delivery, use stream() instead of subscribe(). Streams require event persistence to be enabled.
// subscribe() delivers ephemeral events - missed if subscription inactive
const subscription = await prisma.user.subscribe({
create: { after: true }
});
// stream() delivers persisted events - replays missed events
const stream = await prisma.user.stream({
create: { after: true }
});Note that stream() requires event persistence to be enabled in your Pulse project settings. This ensures events aren't lost during connection interruptions.
Subscription Lifecycle Best Practices:
When building applications with Prisma Pulse, consider using a subscription manager pattern to handle lifecycle, reconnection, and cleanup:
class PulseSubscriptionManager {
private subscriptions = new Map<string, any>();
private reconnectDelay = 1000;
async create(id: string, config: any) {
if (this.subscriptions.size >= 10) {
throw new Error('Maximum subscriptions reached');
}
const subscription = await this.createWithRetry(config);
this.subscriptions.set(id, subscription);
return subscription;
}
private async createWithRetry(config: any, attempt = 0): Promise<any> {
try {
return await prisma.user.subscribe(config);
} catch (error: any) {
if (error.code === 'P6003' && attempt < 3) {
await new Promise(r => setTimeout(r, this.reconnectDelay * (attempt + 1)));
return this.createWithRetry(config, attempt + 1);
}
throw error;
}
}
async stopAll() {
for (const [id, sub] of this.subscriptions) {
sub.stop();
this.subscriptions.delete(id);
}
}
}Connection Heartbeat: Prisma is planning to add heartbeat capability that throws an error when the connection is no longer active, allowing applications to reconnect automatically. Until this feature is available, implement your own heartbeat mechanism using periodic keep-alive messages or timeout detection.
Debugging Tips: Enable Prisma logging to see connection events:
const prisma = new PrismaClient({
log: ['query', 'info', 'warn', 'error'],
});This helps identify whether P6003 errors correlate with specific database operations or network conditions.
P1013: The provided database string is invalid
The provided database string is invalid
P1000: Authentication failed against database server
Authentication failed against database server
P1010: User was denied access on the database
How to fix "P1010: User was denied access on the database" in Prisma
P5008: Usage exceeded, upgrade your plan (Accelerate)
How to fix "Usage exceeded, upgrade your plan" in Prisma Accelerate
P3021: Foreign keys cannot be created on this database
How to fix 'P3021: Foreign keys cannot be created on this database' in Prisma