Debug: HTTP 401 Unauthorized Masih Log Level INFO
Tanggal: 2026-08-17
Endpoint: POST /api/category
Status Code: 401
Log yang muncul:
INFO [13:01:33]: request completed
req: { "method": "POST", "url": "/api/category" }
context: "HTTP"
res: { "statusCode": 401 }
responseTime: 35
Root Cause
Ini memang perilaku yang benar, tapi bukan karena desain yang tepat
Log level INFO pada response 401 bukan bug, melainkan default behavior dari pino-http.
pino-http (library yang digunakan via nestjs-pino) secara default selalu menggunakan level info untuk mencatat log "request completed", tanpa memperhatikan status code response (2xx, 4xx, maupun 5xx), kecuali dikonfigurasi secara eksplisit.
Analisis Kode
1. packages/logger/src/log.config.ts
export const logConfig: Params = {
pinoHttp: {
level: isDev ? "debug" : "info",
// ... transport, serializers, customProps, autoLogging
},
};
Tidak ada customLogLevel di sini. Artinya pino-http menggunakan default-nya, yaitu level info untuk semua request yang selesai — termasuk yang berakhir dengan 4xx dan 5xx.
2. apps/api/src/main.ts
app.useGlobalInterceptors(new LoggerErrorInterceptor());
LoggerErrorInterceptor dari nestjs-pino bekerja untuk exception yang tidak tertangkap (uncaught exception di layer NestJS interceptor), bukan untuk response HTTP yang sudah berhasil ditulis ke client (seperti 401 dari auth guard).
3. apps/api/src/modules/category/category.controller.ts
@Post()
async create(@Body() createCategoryDto: CreateCategoryDto) { ... }
Decorator @AllowAnonymous() sudah dihapus dari endpoint POST /category oleh user. Artinya request ini sekarang dilindungi oleh auth guard dari @thallesp/nestjs-better-auth. Guard menolak request dan mengembalikan 401 — response selesai normal dari sudut pandang HTTP, sehingga pino-http mencatatnya dengan level info.
Kesimpulan
| Pertanyaan |
Jawaban |
Apakah level INFO untuk 401 itu benar? |
Secara teknis benar (itu default pino-http), tapi kurang informatif |
| Apakah ini bug? |
Bukan bug, ini adalah perilaku default yang belum dikonfigurasi |
Mengapa LoggerErrorInterceptor tidak membantu? |
Karena interceptor itu hanya menangkap thrown exception, sedangkan 401 ini dikirim langsung oleh auth guard sebagai HTTP response (bukan throw) |
| Apakah perlu diperbaiki? |
Ya, disarankan — supaya monitoring lebih mudah dan alert bisa dibedakan berdasarkan severity |
Rekomendasi (tidak dilakukan, hanya saran)
Tambahkan customLogLevel di log.config.ts:
pinoHttp: {
customLogLevel: (req, res, err) => {
if (err || res.statusCode >= 500) return 'error';
if (res.statusCode >= 400) return 'warn';
return 'info';
},
// ... konfigurasi lainnya tetap sama
}
Dengan ini:
2xx → INFO
4xx (termasuk 401) → WARN
5xx atau uncaught error → ERROR
File Terkait
| File |
Relevansi |
packages/logger/src/log.config.ts |
Konfigurasi pinoHttp — tidak ada customLogLevel |
apps/api/src/main.ts |
LoggerErrorInterceptor dipasang di sini |
apps/api/src/modules/category/category.controller.ts |
@AllowAnonymous() dihapus dari POST /category — penyebab 401 |
Debug: HTTP 401 Unauthorized Masih Log Level INFO
Tanggal: 2026-08-17
Endpoint:
POST /api/categoryStatus Code: 401
Log yang muncul:
Root Cause
Ini memang perilaku yang benar, tapi bukan karena desain yang tepat
Log level
INFOpada response 401 bukan bug, melainkan default behavior daripino-http.pino-http(library yang digunakan vianestjs-pino) secara default selalu menggunakan levelinfountuk mencatat log "request completed", tanpa memperhatikan status code response (2xx, 4xx, maupun 5xx), kecuali dikonfigurasi secara eksplisit.Analisis Kode
1.
packages/logger/src/log.config.tsTidak ada
customLogLeveldi sini. Artinyapino-httpmenggunakan default-nya, yaitu levelinfountuk semua request yang selesai — termasuk yang berakhir dengan 4xx dan 5xx.2.
apps/api/src/main.tsLoggerErrorInterceptordarinestjs-pinobekerja untuk exception yang tidak tertangkap (uncaught exception di layer NestJS interceptor), bukan untuk response HTTP yang sudah berhasil ditulis ke client (seperti 401 dari auth guard).3.
apps/api/src/modules/category/category.controller.tsDecorator
@AllowAnonymous()sudah dihapus dari endpointPOST /categoryoleh user. Artinya request ini sekarang dilindungi oleh auth guard dari@thallesp/nestjs-better-auth. Guard menolak request dan mengembalikan 401 — response selesai normal dari sudut pandang HTTP, sehinggapino-httpmencatatnya dengan levelinfo.Kesimpulan
INFOuntuk 401 itu benar?LoggerErrorInterceptortidak membantu?Rekomendasi (tidak dilakukan, hanya saran)
Tambahkan
customLogLeveldilog.config.ts:Dengan ini:
2xx→INFO4xx(termasuk 401) →WARN5xxatau uncaught error →ERRORFile Terkait
packages/logger/src/log.config.tspinoHttp— tidak adacustomLogLevelapps/api/src/main.tsLoggerErrorInterceptordipasang di siniapps/api/src/modules/category/category.controller.ts@AllowAnonymous()dihapus dariPOST /category— penyebab 401