{"record":{"id":"32de1d6996649b85","repo":"arsduo/koala","slug":"write-operations-require-an-access-token","errorCode":null,"errorMessage":"Write operations require an access token","messagePattern":"Write operations require an access token","errorType":"exception","errorClass":"Koala::Facebook::AuthenticationError","httpStatus":null,"severity":"error","filePath":"lib/koala/api/graph_api_methods.rb","lineNumber":159,"sourceCode":"      # @example\n      #         graph.put_connections(\"me\", \"feed\", :message => \"Hello, world\")\n      #         => writes \"Hello, world\" to the active user's wall\n      #\n      # Most write operations require extended permissions. For example,\n      # publishing wall posts requires the \"publish_stream\" permission. See\n      # http://developers.facebook.com/docs/authentication/ for details about\n      # extended permissions.\n      #\n      # @param id (see #get_object)\n      # @param connection_name (see #get_connection)\n      # @param args (see #get_connection)\n      # @param options (see #get_object)\n      # @param block (see Koala::Facebook::API#api)\n      #\n      # @return a hash containing the new object's id\n      def put_connections(id, connection_name, args = {}, options = {}, &block)\n        # Posts a certain connection\n        raise AuthenticationError.new(nil, nil, \"Write operations require an access token\") unless access_token\n\n        graph_call(\"#{id}/#{connection_name}\", args, \"post\", options, &block)\n      end\n\n      # Delete an object's connection (for instance, unliking the object).\n      #\n      # @note (see #get_connection)\n      #\n      # @param id (see #get_object)\n      # @param connection_name (see #get_connection)\n      # @args (see #get_connection)\n      # @param options (see #get_object)\n      # @param block (see Koala::Facebook::API#api)\n      #\n      # @return (see #delete_object)\n      def delete_connections(id, connection_name, args = {}, options = {}, &block)\n        # Deletes a given connection\n        raise AuthenticationError.new(nil, nil, \"Delete requires an access token\") unless access_token","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/arsduo/koala/blob/47d052063ef8b5644fb59e279da0b52687999f55/lib/koala/api/graph_api_methods.rb#L141-L177","documentation":"put_connections raises Koala::Facebook::AuthenticationError ('Write operations require an access token') when access_token is nil (lib/koala/api/graph_api_methods.rb:159). Every write to the Graph API — posts, comments, likes, photos, videos — must identify an authenticated user or app, so Koala refuses the call before any HTTP traffic. The guard sits beneath the whole write family: put_object, put_picture, put_video, put_wall_post, put_comment and put_like all raise this same error through it.","triggerScenarios":"api.put_connections('me', 'feed', message: 'hi'), api.put_wall_post('Hello'), api.put_picture(file), api.put_comment(id, 'nice'), api.put_like(id) — any write issued on a Koala::Facebook::API instance constructed without an access token.","commonSituations":"Posting features run for a user whose OAuth token expired and was stored as nil; writing to a Page feed without ever fetching a Page token; delayed jobs enqueued before the token was assigned; test suites building a bare API and expecting HTTP stubs to answer writes.","solutions":["Build the API with the poster's token before any write: Koala::Facebook::API.new(user.facebook_token)","When posting as a Page, fetch and use the Page access token (get_page_access_token) instead of assuming the user token works everywhere","Validate the token is present (and unexpired) before enqueueing write jobs","Rescue Koala::Facebook::AuthenticationError around user-facing writes: clear the stale token, re-run OAuth, retry the post once"],"exampleFix":"# before\napi = Koala::Facebook::API.new\napi.put_wall_post('Hello') # => AuthenticationError: Write operations require an access token\n\n# after\napi = Koala::Facebook::API.new(user.facebook_token)\napi.put_wall_post('Hello', {link: 'https://example.com'})","handlingStrategy":"validation","validationCode":"return reauthenticate_user! unless api.access_token\napi.put_connections('me', 'feed', message: text)","typeGuard":null,"tryCatchPattern":"begin\n  api.put_wall_post(text)\nrescue Koala::Facebook::AuthenticationError\n  user.facebook_token = nil\n  redirect_to login_path # re-run OAuth, then retry the post once\nend","preventionTips":["Gate write features on a present, unexpired token (api.access_token plus token expiry metadata)","Refresh long-lived tokens on a schedule via Koala::Facebook::OAuth#exchange_access_token_info","Pass the token into jobs at enqueue time so serialized writes never lose their posting context","Rescue AuthenticationError around user-facing writes and degrade to a re-login prompt, never a 500"],"tags":["authentication","access-token","write-operations","facebook-graph-api"],"backgroundTag":"missing-access-token","analyzedSha":"47d052063ef8b5644fb59e279da0b52687999f55","analyzedAt":"2026-08-23T10:19:03.891Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}