{"record":{"id":"35fc35bc32a6e6a2","repo":"NativeScript/NativeScript","slug":"no-timer-started-name","errorCode":null,"errorMessage":"No timer started: ${name}","messagePattern":"No timer started: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/profiling/index.ts","lineNumber":60,"sourceCode":"\t\tinfo.currentStart = time();\n\t\tinfo.runCount++;\n\t} else {\n\t\tinfo = {\n\t\t\ttotalTime: 0,\n\t\t\tcount: 0,\n\t\t\tcurrentStart: time(),\n\t\t\trunCount: 1,\n\t\t};\n\t\ttimers[name] = info;\n\t\tprofileNames.push(name);\n\t}\n}\n\nexport function stop(name: string): TimerInfo {\n\tconst info = timers[name];\n\n\tif (!info) {\n\t\tthrow new Error(`No timer started: ${name}`);\n\t}\n\n\tif (info.runCount) {\n\t\tinfo.runCount--;\n\t\tif (info.runCount) {\n\t\t\tinfo.count++;\n\t\t} else {\n\t\t\tinfo.lastTime = time() - info.currentStart;\n\t\t\tinfo.totalTime += info.lastTime;\n\t\t\tinfo.count++;\n\t\t\tinfo.currentStart = 0;\n\t\t}\n\t} else {\n\t\tthrow new Error(`Timer ${name} paused more times than started.`);\n\t}\n\n\treturn info;\n}","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/NativeScript/NativeScript/blob/6800aefa6511d23ddad8beb38ccc8541c5e91628/packages/core/profiling/index.ts#L42-L78","documentation":"profiling.stop(name) looks up the timer registered by a prior profiling.start(name); if no timer with that name exists it throws 'No timer started: <name>'. Timers live in a module-level registry, so stop() must be paired exactly with a start() that ran earlier in the same session.","triggerScenarios":"Calling profiling.stop('x') without a matching profiling.start('x'); calling stop twice after start's runCount is exhausted; typos in the timer name; profiling enabled via __NS_PROFILE__ flags but stop() invoked for a name never registered.","commonSituations":"Conditional start() paths skipped (early return, error thrown) while stop() runs unconditionally; renaming a timer in one place but not the other; module loaded twice (different paths) so the registry is split.","solutions":["Ensure profiling.start(name) is called before stop(name) with the identical string.","Guard: if (profiling.timerExists && profiling.timerExists(name)) before stopping (or wrap in try/catch).","Pair start/stop in try/finally so failures still stop the timer exactly once.","Verify no duplicate module instances are splitting the timer registry."],"exampleFix":"// before\ntry {\n  profiling.start('render');\n  doWork();\n} finally {\n  profiling.stop('render'); // throws if start never ran\n}\n// after\nprofiling.start('render');\ntry {\n  doWork();\n} finally {\n  if (profiling.timerExists('render')) profiling.stop('render');\n}","handlingStrategy":"try-catch","validationCode":"import * as profiling from '@nativescript/core/profiling';\n//\nif (!profiling.timerExists || profiling.timerExists(name)) { // guard if API available\n  profiling.stop(name);\n}","typeGuard":"function canStop(name) {\n  try { profiling.stop(name); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  profiling.stop(name);\n} catch (e) {\n  if (String(e.message).startsWith('No timer started:')) {\n    // ignore or start+stop a no-op timer\n  } else throw e;\n}","preventionTips":["Pair every start() with exactly one stop() using a shared name constant.","Put stop() in a finally block only after start() succeeded.","Extract timer names into constants to avoid typos.","Never stop the same timer twice."],"tags":["profiling","timer","state"],"backgroundTag":"timer-not-started","analyzedSha":"6800aefa6511d23ddad8beb38ccc8541c5e91628","analyzedAt":"2026-08-30T20:04:56.809Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}