Skip to content

Decoding issue with VersionedCodec #162

Description

@blackwiz4rd

Hello,
I've had an issue with JsonDecodingException.

Proposed resolution is to use SafeCodec version of VersionedCodec, but ideally, the encode/decode should include try/catch for these exceptions directly:

package com.rch.rchpay.kstore.di

import io.github.xxfast.kstore.Codec
import kotlinx.serialization.SerializationException

/**
 * Wraps any [Codec] to handle corrupted or empty store files gracefully.
 *
 * kstore's built-in codecs can throw uncaught [SerializationException] when store files
 * are empty or corrupted. For example:
 * - [io.github.xxfast.kstore.file.extensions.VersionedCodec] crashes when both the main
 *   store file and the `.version` file are empty/corrupted.
 * - [io.github.xxfast.kstore.file.FileCodec] only catches [FileNotFoundException] but not
 *   [SerializationException] from invalid JSON.
 *
 * This wrapper catches serialization exceptions and returns null, treating the store as empty
 * rather than crashing the application. The next successful [encode] will repair the file.
 */
internal class SafeCodec<T : Any>(
    private val delegate: Codec<T>,
) : Codec<T> {

    override suspend fun decode(): T? = try {
        delegate.decode()
    } catch (_: SerializationException) {
        null
    } catch (_: Exception) {
        null
    }

    override suspend fun encode(value: T?) {
        delegate.encode(value)
    }
}

Issue with json decoding exception:

Fatal Exception: kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 0: Expected numeric literal at path: $
JSON input: 
       at kotlinx.serialization.SerializationException.<init>(SerializationException.java:51)
       at kotlinx.serialization.json.internal.JsonException.<init>(JsonException.java:16)
       at kotlinx.serialization.json.internal.JsonDecodingException.<init>(JsonDecodingException.java:21)
       at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
       at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
       at kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:580)
       at kotlinx.serialization.json.internal.AbstractJsonLexer.fail$default(AbstractJsonLexer.kt:578)
       at kotlinx.serialization.json.internal.AbstractJsonLexer.consumeNumericLiteral(AbstractJsonLexer.kt:646)
       at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeInt(StreamingJsonDecoder.kt:297)
       at kotlinx.serialization.internal.IntSerializer.deserialize(Primitives.kt:96)
       at kotlinx.serialization.internal.IntSerializer.deserialize(Primitives.kt:92)
       at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
       at kotlinx.serialization.json.internal.JsonStreamsKt.decodeByReader(JsonStreams.kt:111)
       at kotlinx.serialization.json.io.IoStreamsKt.decodeFromSource(IoStreams.kt:63)
       at io.github.xxfast.kstore.file.extensions.VersionedCodec.decode(VersionedCodec.java:69)
       at io.github.xxfast.kstore.KStore$read$2.invokeSuspend(KStore.kt:62)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:101)
       at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.java:113)
       at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:89)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.java:589)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:823)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:720)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:707)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions