{"record":{"id":"8fecf3ae06d9e8da","repo":"arsduo/koala","slug":"unliking-requires-an-access-token","errorCode":null,"errorMessage":"Unliking requires an access token","messagePattern":"Unliking requires an access token","errorType":"exception","errorClass":"Koala::Facebook::AuthenticationError","httpStatus":null,"severity":"error","filePath":"lib/koala/api/graph_api_methods.rb","lineNumber":338,"sourceCode":"      # @param block (see Koala::Facebook::API#api)\n      #\n      # @return (see #put_connections)\n      def put_like(id, options = {}, &block)\n        # Likes the given post.\n        put_connections(id, \"likes\", {}, options, &block)\n      end\n\n      # Unlike a given object.\n      # Convenience method equivalent to delete_connection(id, \"likes\").\n      #\n      # @param id (see #get_object)\n      # @param options (see #get_object)\n      # @param block (see Koala::Facebook::API#api)\n      #\n      # @return (see #delete_object)\n      def delete_like(id, options = {}, &block)\n        # Unlikes a given object for the logged-in user\n        raise AuthenticationError.new(nil, nil, \"Unliking requires an access token\") unless access_token\n        graph_call(\"#{id}/likes\", {}, \"delete\", options, &block)\n      end\n\n      # Search for a given query among visible Facebook objects.\n      # See {http://developers.facebook.com/docs/reference/api/#searching Facebook documentation} for more information.\n      #\n      # @param search_terms the query to search for\n      # @param args object type and any additional arguments, such as fields, etc.\n      # @param options (see #get_object)\n      # @param block (see Koala::Facebook::API#api)\n      #\n      # @return [Koala::Facebook::API::GraphCollection] an array of search results\n      def search(search_terms, args = {}, options = {}, &block)\n        # Normally we wouldn't enforce Facebook API behavior, but the API fails with cryptic error\n        # messages if you fail to include a type term. For a convenience method, that is valuable.\n        raise ArgumentError, \"type must be includedin args when searching\" unless args[:type] || args[\"type\"]\n        graph_call(\"search\", args.merge(\"q\" => search_terms), \"get\", options, &block)\n      end","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/arsduo/koala/blob/47d052063ef8b5644fb59e279da0b52687999f55/lib/koala/api/graph_api_methods.rb#L320-L356","documentation":"delete_like raises Koala::Facebook::AuthenticationError ('Unliking requires an access token') when access_token is nil (lib/koala/api/graph_api_methods.rb:338). Unliking issues DELETE on '<id>/likes' as the logged-in user, so it can never run unauthenticated; Koala enforces this before any HTTP request (nil http_status on the error). put_like fails symmetrically through the put_connections guard with 'Write operations require an access token'.","triggerScenarios":"api.delete_like(post_id) — or any unlike flow built on it — where the API instance was constructed without a token, e.g. Koala::Facebook::API.new(session[:fb_token]) with the session value expired or cleared to nil.","commonSituations":"Unlike buttons in controllers whose current_user token is nil after session expiry; tokens invalidated by password changes or Facebook app deauthorization while the UI still shows the like toggle; per-request API clients where one code path forgets to assign the token.","solutions":["Guard the session token before constructing the API: send the user back to login when session[:fb_token] is nil","Construct the API with the user's valid token and only then call delete_like","On Facebook deauthorization callbacks, clear local like state so the UI stops offering unlikes with a dead token","Rescue Koala::Facebook::AuthenticationError, restart OAuth, and retry the unlike once"],"exampleFix":"# before\ndef unlike\n  api = Koala::Facebook::API.new(session[:fb_token]) # nil after expiry/logout\n  api.delete_like(params[:post_id])\nend\n\n# after\ndef unlike\n  token = session[:fb_token] or return redirect_to(login_path)\n  api = Koala::Facebook::API.new(token)\n  api.delete_like(params[:post_id])\nend","handlingStrategy":"validation","validationCode":"return reauthenticate! unless api.access_token\napi.delete_like(post_id)","typeGuard":null,"tryCatchPattern":"begin\n  api.delete_like(post_id)\nrescue Koala::Facebook::AuthenticationError\n  reauthenticate! # clear stale token, restart OAuth, retry the unlike once\nend","preventionTips":["Treat a nil session token as 'not logged in' at the controller level, before any Graph call","Prune local like state when Facebook sends app deauthorization callbacks","Keep like and unlike symmetric: both check token presence first","Stub tokens in controller tests to exercise the unlike path"],"tags":["authentication","access-token","unlike","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"}