{"record":{"id":"f7e4c57b6ff7bd29","repo":"google/ExoPlayer","slug":"spurious-audio-timestamp-system-clock-mismatch","errorCode":null,"errorMessage":"Spurious audio timestamp (system clock mismatch): {audioTimestampPositionFrames}, {audioTimestampSystemTimeUs}, {systemTimeUs}, {playbackPositionUs}, {submittedFrames}, {writtenFrames}","messagePattern":"Spurious audio timestamp \\(system clock mismatch\\): (.+?), (.+?), (.+?), (.+?), (.+?), (.+?)","errorType":"exception","errorClass":"AudioSink.InvalidAudioTrackTimestampException","httpStatus":null,"severity":"warning","filePath":"library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java","lineNumber":1994,"sourceCode":"        long audioTimestampPositionFrames,\n        long audioTimestampSystemTimeUs,\n        long systemTimeUs,\n        long playbackPositionUs) {\n      String message =\n          \"Spurious audio timestamp (system clock mismatch): \"\n              + audioTimestampPositionFrames\n              + \", \"\n              + audioTimestampSystemTimeUs\n              + \", \"\n              + systemTimeUs\n              + \", \"\n              + playbackPositionUs\n              + \", \"\n              + getSubmittedFrames()\n              + \", \"\n              + getWrittenFrames();\n      if (failOnSpuriousAudioTimestamp) {\n        throw new InvalidAudioTrackTimestampException(message);\n      }\n      Log.w(TAG, message);\n    }\n\n    @Override\n    public void onInvalidLatency(long latencyUs) {\n      Log.w(TAG, \"Ignoring impossibly large audio latency: \" + latencyUs);\n    }\n\n    @Override\n    public void onPositionAdvancing(long playoutStartSystemTimeMs) {\n      if (listener != null) {\n        listener.onPositionAdvancing(playoutStartSystemTimeMs);\n      }\n    }\n\n    @Override\n    public void onUnderrun(int bufferSize, long bufferSizeMs) {","sourceCodeStart":1976,"sourceCodeEnd":2012,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java#L1976-L2012","documentation":"DefaultAudioSink listens to AudioTimestamp (via AudioTrack.getTimestamp) to keep playback positions accurate. A timestamp frame position that is farther in the future than the frames actually submitted to the track indicates the device's timestamp clock disagrees with the system clock (a known firmware/driver bug). Depending on failOnSpuriousAudioTimestamp (DefaultAudioSink.Builder experimental flag, default false), the sink either logs a warning ('Spurious audio timestamp (system clock mismatch)...') or throws InvalidAudioTrackTimestampException with the same diagnostic tuple: position frames, timestamp system time, current system time, playback position, submitted and written frames.","triggerScenarios":"A device AudioTrack reports a timestamp whose audioTimestampSystemTimeUs implies more audio played than has been written — clock skew or buggy timestamping on certain chipsets — and the app enabled setFailOnSpuriousAudioTimestamp(true) on the sink builder.","commonSituations":"Bespoke/older firmware or emulators with drifting CLOCK_MONOTONIC vs audio DSP clocks; long playback sessions on affected devices; users enabling the fail-fast experimental flag for test builds; usually benign if left at the default warning behavior.","solutions":["Keep the default behavior (do not call setFailOnSpuriousAudioTimestamp(true)) so mismatches are only logged.","If you need fail-fast in QA builds, wrap playback in a catch for InvalidAudioTrackTimestampException and recreate the player to resynchronize.","Report the device model/Android version with the diagnostic tuple — this is a device firmware issue, not app logic.","Periodically re-sync or restart playback on affected devices when warnings spam the log."],"exampleFix":"// before\nnew DefaultAudioSink.Builder(ctx)\n    .setFailOnSpuriousAudioTimestamp(true) // throws on flaky devices\n    .build();\n\n// after\nnew DefaultAudioSink.Builder(ctx)\n    .setFailOnSpuriousAudioTimestamp(false) // default: log-only\n    .build();","handlingStrategy":"try-catch","validationCode":"// before enabling fail-fast behavior, screen known-affected devices\nboolean riskyDevice = Build.MODEL in AFFECTED_MODELS;\nsinkBuilder.setFailOnSpuriousAudioTimestamp(!riskyDevice);","typeGuard":null,"tryCatchPattern":"try {\n  player.play();\n} catch (Exception e) {\n  if (e instanceof AudioSink.InvalidAudioTrackTimestampException\n      || e.getCause() instanceof AudioSink.InvalidAudioTrackTimestampException) {\n    recreatePlayerAndSeekTo(player.getCurrentPosition()); // resync timestamps\n  }\n}","preventionTips":["Leave setFailOnSpuriousAudioTimestamp at default false","Monitor Logcat for 'Spurious audio timestamp' on new device models","File device-specific reports with the diagnostic tuple","Avoid enabling fail-fast flags in production builds"],"tags":["exoplayer","audio","audiotrack","timestamp","firmware"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}