{"record":{"id":"ac5be318c31dc934","repo":"pinpoint-apm/pinpoint","slug":"traceblock-already-begin-trace","errorCode":null,"errorMessage":"TraceBlock already begin. trace={}","messagePattern":"TraceBlock already begin\\. trace=(.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DefaultTraceBlock.java","lineNumber":60,"sourceCode":"    private boolean begin;\n\n    public DefaultTraceBlock(Trace trace) {\n        this.trace = Objects.requireNonNull(trace, \"trace\");\n    }\n\n    @Override\n    public void close() {\n        // AutoCloseable\n        if (begin) {\n            trace.traceBlockEnd();\n        }\n    }\n\n    @Override\n    public void begin() {\n        if (begin) {\n            if (logger.isWarnEnabled()) {\n                logger.warn(\"TraceBlock already begin. trace={}\", trace);\n            }\n            return;\n        }\n        trace.traceBlockBegin();\n        begin = true;\n    }\n\n    public boolean isBegin() {\n        return begin;\n    }\n\n    @Override\n    public Trace getTrace() {\n        return trace;\n    }\n\n    @Override\n    public ParsingResult recordSqlInfo(String sql) {","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DefaultTraceBlock.java#L42-L78","documentation":"DefaultTraceBlock.begin() logs 'TraceBlock already begin. trace={}' when begin() is called on a block that was already marked as begun. The method guards its `begin` flag and returns without calling trace.traceBlockBegin() again, so the second begin is silently skipped. This is a usage-order problem with DefaultTraceBlock helper objects.","triggerScenarios":"Reusing a DefaultTraceBlock instance and calling begin() twice without an intervening end(); wrapping overlapping code regions with the same block object; a begin() call retried after a previous begin already succeeded.","commonSituations":"Application or plugin code using DefaultTraceBlock helpers around nested/re-entrant methods; copy-pasted instrumentation where one block object wraps two sequential sections but begin() was called for both; re-entrant method interception.","solutions":["Create a new DefaultTraceBlock instance for each instrumentation section instead of reusing one","Call end() before calling begin() again on the same block","Restructure re-entrant/instrumented code so each begin/end pair is balanced per invocation","If this appears with recursion, use a separate block per stack frame"],"exampleFix":"// before\nDefaultTraceBlock block = new DefaultTraceBlock(trace);\nblock.begin();\na();\nblock.begin(); // warns already begin\nb();\nblock.end();\n// after\nDefaultTraceBlock b1 = new DefaultTraceBlock(trace);\nb1.begin(); a(); b1.end();\nDefaultTraceBlock b2 = new DefaultTraceBlock(trace);\nb2.begin(); b(); b2.end();","handlingStrategy":"type-guard","validationCode":"if (!block.isBegin()) { block.begin(); }","typeGuard":"boolean canBegin(DefaultTraceBlock b) { return b != null && !b.isBegin(); }","tryCatchPattern":"if (block.isBegin()) { logger.warn(\"block already begun, skipping\"); } else { block.begin(); }","preventionTips":["Use a fresh DefaultTraceBlock per section, never reuse","Balance begin()/end() calls with try/finally","Avoid wrapping re-entrant methods with a single shared block","Assert block state in tests for instrumented code"],"tags":["java","trace-block","instrumentation","pinpoint-profiler"],"backgroundTag":"invalid-state-transition","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}