Readonly reactive variables in pinia store
I am trying to mark a reactive variable in my pinia store as readonly() so it's only changed via setter but doing that yields a warning as
[Vue warn] Set operation on key "value" failed: target is readonly. on initial page load.
How can I solve this?9 Replies
Hi @zigglearner1235. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
The knowledge sources do not explicitly mention a recommended way to mark a reactive variable in a Pinia store as readonly so that it can only be changed via a setter. However, based on the provided examples, the typical pattern in Pinia is to keep state variables mutable within the store and expose actions (setters) to modify them. You can control access by only using the setter in your components, but the state itself is not truly readonly—it's just a convention.
If you attempt to wrap a Pinia state variable with Vue's readonly(), you will encounter the warning you described:
[Vue warn] Set operation on key "value" failed: target is readonly. This is expected, as readonly refs cannot be mutated directly.
A common approach is to only expose the state via getters or computed properties if you want to prevent direct mutation from outside the store. For example, you can return a computed property from your store that reads the state, but only provide mutation methods (actions) for changing it. This way, consumers of the store cannot mutate the state directly, but only through the defined actions.
Here’s a simplified example based on the patterns shown in the sources:
In this pattern, myValue is readonly from the outside, and only setMyValue can change it. This approach is not enforced at the type level, but it is a common convention in Pinia stores for encapsulation and control over state changes.
If you need stricter enforcement, you would need to rely on code conventions and not expose the raw ref outside the store, as there is no built-in Pinia mechanism for making state truly readonly while still allowing internal mutation via actions.
For more on Pinia store patterns, see the Nuxt state management documentation and the Pinia documentation referenced in the migration guide here.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@1290550861109657600> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai it only gives the warning on page load btw
Let me check the knowledge base for you again. One moment! :books:
----------------------
I'm sorry, but the knowledge sources do not explicitly address why wrapping a Pinia store state variable with readonly() only gives a warning on page load and not during later mutations. The sources do confirm that making a Pinia state variable readonly will cause Vue to warn about failed set operations, but they do not provide further details about the timing or lifecycle of these warnings.
The recommended approach, as shown in the sources, is to expose state via computed properties or getters and only allow mutation through actions, rather than using readonly() on the state itself. This avoids the warning and achieves the intended encapsulation pattern in Pinia stores, but does not enforce strict immutability at the reactivity level Extending or composing Pinia setup stores for reusable getters, setters and actions.
If you need more specific behavior or error handling, the knowledge sources do not provide enough information to offer a solution.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
<@1290550861109657600> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai pinia docs says not returning a ref is a bad practice so
Let me check the knowledge base for you again. One moment! :books:
----------------------
The knowledge sources do not explicitly mention that returning a computed or readonly ref from a Pinia store is considered bad practice, nor do they state that you must always return raw refs. The examples in the sources show returning refs directly from the store, which is the standard pattern, but they do not provide a rule against returning computed or readonly refs.
For example, the recommended Pinia store pattern is:
Here, both refs and computed properties are returned, and there is no warning or mention of bad practice regarding returning computed values Extending or composing Pinia setup stores for reusable getters, setters and actions.
The Nuxt documentation also shows returning refs from composables and stores, but does not state that returning a computed or readonly ref is discouraged State Management.
If you have seen a statement in the Pinia docs about not returning a ref being bad practice, it is not reflected in the knowledge sources provided. If you want to enforce immutability, the common pattern is to return a computed property (which is readonly by default) and only expose mutation through actions, as shown in the previous examples.
If you need more specific guidance, the knowledge sources do not provide further details.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
<@1290550861109657600> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
How do you guys do this? The real people.