Skip to content

Dargon789 patch 1#6

Open
Dargon789 wants to merge 7 commits into
ijjk:canaryfrom
Dargon789:Dargon789-patch-1
Open

Dargon789 patch 1#6
Dargon789 wants to merge 7 commits into
ijjk:canaryfrom
Dargon789:Dargon789-patch-1

Conversation

@Dargon789
Copy link
Copy Markdown

No description provided.

Dargon789 and others added 2 commits January 17, 2026 15:02
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Copy link
Copy Markdown
Author

@Dargon789 Dargon789 left a comment

Choose a reason for hiding this comment

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

Dargon789 and others added 5 commits January 17, 2026 16:00
* Create SECURITY.md

Documentation:

Introduce SECURITY.md with information on supported versions and placeholders for vulnerability reporting procedures.
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

* Update SECURITY.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>

---------

Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com>
ijjk pushed a commit that referenced this pull request Apr 27, 2026
…leLog (vercel#92329)

## Background: three sources of file log entries

Browser `console.*` calls in Next.js dev mode are forwarded to the
server over a WebSocket. Before this PR, three independent mechanisms
wrote to the `.next/logs/next-development.log` file:

1. **`ClientFileLogger`** (client → `client-file-logs` WS event →
`handleClientFileLogs`) — a class in `forward-logs.ts` that intercepted
every `console.*` call unconditionally, serialized args into
message-only strings (no stack traces, no source mapping), and sent them
to the server over a separate `client-file-logs` WebSocket event. The
server's `handleClientFileLogs` wrote them directly to the file logger
as `Browser` entries.

2. **`handleLog` direct file writes** (client → `browser-logs` WS event
→ `handleLog` → `fileLogger`) — the primary path. The browser's patched
console methods serialize args into `ClientLogEntry` objects, batch
them, and send them as `browser-logs` WebSocket events. On the server,
`handleLog` in `receive-logs.ts` deserializes the args, source-maps
stack traces, and forwards to the terminal. As a side effect, it also
wrote directly to the file logger.

3. **`console-file.tsx` interception** (server-side `console.*` →
`fileLogger.logServer`) — a server-side environment extension that
patches the server process's own `console.*` methods. When `handleLog`
calls `forwardConsole.error()` to print browser logs to the terminal,
this interception captures that output and writes it as a `Server`
entry. The `[browser]` text visible in these entries' messages is the
terminal prefix leaking into the file log.

## Problems with the old system

### Duplicate entries

On the client side, `createLogEntry` gated the `browser-logs` send
behind `isTerminalLoggingEnabled`:

```javascript
if (!isTerminalLoggingEnabled) {
  return  // skip browser-logs WebSocket send
}
```

But `clientFileLogger.log()` was called **before** this check,
unconditionally. So `ClientFileLogger` always produced file log entries
regardless of config.

Meanwhile, `handleLog` was gated by `browserToTerminalConfig` in both
hot reloaders. Because `experimental.browserDebugInfoInTerminal`
defaults to `'warn'`, this gate was open by default — `handleLog` ran
for errors and warnings even in code without explicit
`logging.browserToTerminal` config, like this test. But `console.log`
was filtered out at the `'warn'` level, so only `ClientFileLogger` wrote
those.

The net effect: errors and warnings were written to the file by **both**
`ClientFileLogger` (message-only) and `handleLog` (with source-mapped
stacks), producing duplicates. `console.log` was written only by
`ClientFileLogger`.

### Mislabeled source

The direct file writes inside `handleLog` had a bug: the
`any-logged-error` and `formatted-error` code paths hardcoded
`fileLogger.logBrowser()` instead of checking `isServerLog`. The
`console` kind already checked `isServerLog` correctly. This
inconsistency meant that when a server-decorated error (one with the
`Symbol.for('NextjsError')` property set by `decorateServerError`) was
logged via `console.error(serverError)` in the browser, the `sourceType`
would be legitimately set to `'server'`, but the file log entry would
still be labeled `Browser`.

This bug didn't manifest in this test because the test calls
`console.error('string')` with no Error objects — `forwardErrorLog`
never finds an Error to call `getErrorSource` on, so `sourceType`
remains `undefined` and `isServerLog` is `false`. The hardcoded
`logBrowser` happened to produce the correct label by coincidence.

### The result

With the default config, a single `console.error('string')` in the
browser produced **three** file log entries:

1. `Browser ERROR` (message-only) — from `ClientFileLogger`
2. `Browser ERROR` (with stack) — from `handleLog`'s direct file write
(hardcoded `logBrowser`)
3. `Server ERROR` (with stack + `[browser]` prefix) — from
`console-file.tsx` intercepting `handleLog`'s `forwardConsole.error()`
terminal output

## What this PR does

**Removes `ClientFileLogger` and the `client-file-logs` channel
entirely.** File logging now happens via `handleLog`'s direct writes and
`console-file.tsx` interception.

**Decouples the client-side send from terminal logging.** The old
`createLogEntry` gated the `browser-logs` send on
`isTerminalLoggingEnabled`. The new code gates on `shouldForwardLogs`:

```javascript
const shouldForwardLogs = isTerminalLoggingEnabled || !!process.env.__NEXT_MCP_SERVER
```

This is the key mechanism that makes consolidation possible —
`browser-logs` events now fire when either terminal logging or the MCP
server (which controls file logging) is enabled, so `handleLog` always
receives the entries it needs.

**Decouples server-side file logging from terminal output.** `handleLog`
is no longer gated by `browserToTerminalConfig` at the hot-reloader
level — it always runs. Inside `handleLog`, terminal output and file
logging are controlled independently: `shouldShowEntry(entry, config)`
gates terminal output, `fileLogger.isEnabled()` gates file writes.

**Fixes the `isServerLog` labeling bug.** All entry kinds (`console`,
`any-logged-error`, `formatted-error`) now check `isServerLog` and call
`logServer()`/`logBrowser()` accordingly.

## Snapshot diff explanation

### Old snapshot (7 entries)

```
1. Browser LOG   — "Complex circular object: ..."        ← ClientFileLogger
2. Browser ERROR — "message"                             ← ClientFileLogger (message-only)
3. Browser WARN  — "message"                             ← ClientFileLogger (message-only)
4. Server ERROR  — "[browser] message + stack + loc"     ← console-file.tsx (intercepting forwardConsole.error)
5. Browser ERROR — "message + stack + loc"               ← handleLog any-logged-error (hardcoded logBrowser)
6. Server WARN   — "[browser] message + loc"             ← console-file.tsx (intercepting forwardConsole.warn)
7. Browser WARN  — "message"                             ← handleLog console kind (logBrowser, isServerLog=false)
```

### New snapshot (5 entries)

```
1. Browser LOG   — "Complex circular object: ..."        ← handleLog console kind (logBrowser)
2. Browser ERROR — "message + stack + loc"               ← handleLog any-logged-error (logBrowser)
3. Server ERROR  — "[browser] message + stack + loc"     ← console-file.tsx (intercepting forwardConsole.error)
4. Browser WARN  — "message"                             ← handleLog console kind (logBrowser)
5. Server WARN   — "[browser] message + loc"             ← console-file.tsx (intercepting forwardConsole.warn)
```

### What changed

With `ClientFileLogger` removed, each `console.*` call now produces one
`Browser` entry from `handleLog` instead of two (ClientFileLogger
message-only + handleLog with stack). Per call:

- **`console.log`**: old `#1` (ClientFileLogger) → new `#1` (handleLog).
Previously only `ClientFileLogger` wrote this — `handleLog` skipped it
because `log` level was below the `'warn'` terminal threshold. Now
`handleLog` writes file logs for all entry kinds before the `shouldShow`
check.
- **`console.error`**: old `#2` (ClientFileLogger duplicate) removed.
Old `#5` (handleLog) → new `#2`, now with cleaner formatting.
- **`console.warn`**: old `#3` (ClientFileLogger duplicate) removed. Old
`#7` (handleLog) → new `#4`.
- **`console-file.tsx` entries unchanged**: old `#4`/`#6` → new
`#3`/`#5`. These are artifacts of `console-file.tsx` intercepting the
server process's terminal output, not from `handleLog` directly.
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