Skip to content

setMetadata() method merges existing with new data? #597

Description

@jgeewax

Looks like if I call setMetadata on an object, it merges the data with what's in production...

var bucket = ...; // Get a bucket somehow.
var file = bucket.file('my-file');

file.setMetadata({
  metadata: {
    first: 'first'
  }
});

file.setMetadata({
  metadata: {
    second: 'second'
  }
}, function(err, metadata) {
  // metadata here is {first: 'first', second: 'second'}
  // Expected it to be just {second: 'second'} ....
});

I suspect that we can't .. fix this all that much... but maybe we can at least document it ?


The options we have so far:

  • Make metadata immutable: remove setMetadata
  • Operate on a single attribute at a time: getMetadata(key) and setMetadata(key, value)
  • Rename setMetadata to patchMetadata or mergeMetadata
  • Add some documentation about the behavior of setMetadata

/cc @Capstan @aozarov

Activity

  1. added
    type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.
    api: storageIssues related to the Cloud Storage API.
    on May 13, 2015
  2. added this to the Storage Stable milestone on May 13, 2015
  3. added
    type: questionRequest for information or clarification. Not an issue.
    on May 13, 2015
  4. ryanseys commented on May 13, 2015

    @ryanseys
    Contributor

    Remember #459? Yeah we switched to PATCH because using PUT destroyed ACLs with BigQuery, making our datasets inaccessible. I'm not sure if this is also the case with Storage but I feel it would be appropriate to remain consistent across our APIs in this library.

  5. ryanseys commented on May 13, 2015

    @ryanseys
    Contributor

    We can still document it for our users. If they want to delete an existing value, I believe the correct way is to set it to null.

  6. aozarov commented on May 13, 2015

    @aozarov

    Yes, but I doubt if doing it (delete and set) should be done by the library as it can fail in the middle and leave it in an undesired state.

    BTW, nulls may be a separate issue which I mentioned to @jgeewax.
    In Java nulls are considered as "ignore" in patch operation and instead a special "null" value should be used (e.g. http://javadoc.google-http-java-client.googlecode.com/hg/latest/com/google/api/client/util/Data.html#NULL_BIG_DECIMAL) [which clearly should be done transparently by the library]. Not sure if the same problem applies to node.js apiary client.

  7. ryanseys commented on May 13, 2015

    @ryanseys
    Contributor

    I doubt if doing it (delete and set) should be done by the library as it can fail in the middle and leave it in an undesired state.

    The API call operation is atomic so either the whole thing succeeds or fails.

  8. ryanseys commented on May 13, 2015

    @ryanseys
    Contributor

    I think I see what you were saying. I meant that using PATCH you can delete existing values by setting them to null. We never make 2 calls for setting metadata. That requires you to know about the ones are set already, which is a getMetadata call away. We leave this as an exercise for the user if they want to do that.

  9. aozarov commented on May 13, 2015

    @aozarov

    What I was saying is that we should probably not do the following:

    func setMetadata(blob, metadata) {
      rpc.patch(blob, {"metadata": null})
      rpc.patch(blob, {"metadata": metadata})
    }
    
  10. ryanseys commented on May 13, 2015

    @ryanseys
    Contributor

    Oh we'd never do that. The end result is the same as just rpc.patch(blob, {"metadata": metadata})

    I meant if you wanted to set completely new metadata, including destroying the ones currently set, you need to know the existing ones and set them to null so as to achieve the same result as using PUT.

  11. ryanseys commented on May 13, 2015

    @ryanseys
    Contributor

    Like this:

    // metadata is currently { a: '1', b: '2', c: '3' };
    rpc.patch(blob, { metadata: { a: 'x', b: null, c: null } }) // need to know b and c exist so you can set them to null
    // metadata is now { a: 'x' };

    This is the same as:

    // metadata is currently { a: '1', b: '2', c: '3' };
    rpc.put(blob, { metadata: { a: 'x' } })
    // metadata is now { a: 'x' };
  12. aozarov commented on May 13, 2015

    @aozarov

    Is it? Is rpc.put doing an update (https://cloud.google.com/storage/docs/json_api/v1/objects/update)?
    If so, wouldn't it clear out the other Blob's user-given properties (e.g. contentLanguage)?

  13. jgeewax commented on May 13, 2015

    @jgeewax
    ContributorAuthor

    So back to the main issue:

    My concern here is that set typically means "replace the value up there with the value I'm sending from down here". set to us means... "merge this value from down here into whatever data exists up there."

    Can we rename anything ? or are we just OK with adding some docs that explain this? Or do we try to get Google to fix something ? What makes the most sense as a user of this library?

  14. aozarov commented on May 13, 2015

    @aozarov

    I doubt that a function that can only append is that useful.
    One options (until fixed by the backed) would be to make it a read-only property which can only be set when creating a new file. Once apiary fix the issue property can become again read-write.

  15. 34 remaining items

  16. added a commit that references this issue on Feb 2, 2026
    7fcfd40
  17. added a commit that references this issue on Feb 3, 2026
  18. added a commit that references this issue on Feb 3, 2026
    88af461
  19. added a commit that references this issue on Feb 25, 2026
  20. added a commit that references this issue on Mar 18, 2026
  21. added a commit that references this issue on Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

api: storageIssues related to the Cloud Storage API.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.type: questionRequest for information or clarification. Not an issue.

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions