{"record":{"id":"012da3e53415d664","repo":"instructure/canvas-lms","slug":"partner-id-partner-key-are-required","errorCode":null,"errorMessage":"partner_id & partner_key are required","messagePattern":"partner_id & partner_key are required","errorType":"exception","errorClass":"Canvas::Migration::Error","httpStatus":null,"severity":"error","filePath":"gems/plugins/academic_benchmark/lib/academic_benchmark/outcome_data/from_api.rb","lineNumber":26,"sourceCode":"# Canvas is free software: you can redistribute it and/or modify it under\n# the terms of the GNU Affero General Public License as published by the Free\n# Software Foundation, version 3 of the License.\n#\n# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more\n# details.\n#\n# You should have received a copy of the GNU Affero General Public License along\n# with this program. If not, see <http://www.gnu.org/licenses/>.\n\nmodule AcademicBenchmark\n  module OutcomeData\n    class FromApi < Base\n      def initialize(options = {})\n        super(options.merge(AcademicBenchmark.config))\n        unless partner_id.present? && partner_key.present?\n          raise Canvas::Migration::Error,\n                \"partner_id & partner_key are required\"\n        end\n      end\n      delegate :authority, :publication, :partner_id, :partner_key, to: :@options\n\n      def data\n        @data ||= api.standards.send(api_method, guid, include_obsolete_standards: false, exclude_examples: true)\n      end\n\n      def error_message\n        \"Couldn't update standards for guid '#{guid}'\"\n      end\n\n      private\n\n      def api\n        @_api ||= AcademicBenchmarks::Api::Handle.new(\n          partner_id:,","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/gems/plugins/academic_benchmark/lib/academic_benchmark/outcome_data/from_api.rb#L8-L44","documentation":"Canvas::Migration::Error raised in OutcomeData::FromApi#initialize when, after merging AcademicBenchmark.config into the options, partner_id or partner_key is blank. The API client cannot authenticate against the Academic Benchmarks service without both credentials.","triggerScenarios":"Constructing OutcomeData::FromApi (via load_data with authority/publication options) where options lack partner_id/partner_key and the academic_benchmark plugin config does not supply them.","commonSituations":"Unconfigured plugin in a new environment; config present but keys empty strings; passing options that don't include credentials and expecting config to fill them when it can't.","solutions":["Configure both partner_id and partner_key in the academic_benchmark plugin settings.","Pass them explicitly: OutcomeData.load_data(authority: x, partner_id: pid, partner_key: key).","Verify AcademicBenchmark.config returns non-blank values in the environment where the job runs.","If data is available locally, use the archive_file path to avoid the API entirely."],"exampleFix":"// before\nOutcomeData::FromApi.new(authority: 'XYZ')\n// after\nOutcomeData::FromApi.new(authority: 'XYZ', partner_id: config[:partner_id], partner_key: config[:partner_key])","handlingStrategy":"validation","validationCode":"merged = options.merge(AcademicBenchmark.config || {})\nunless merged[:partner_id].present? && merged[:partner_key].present?\n  raise 'partner_id & partner_key must be configured'\nend","typeGuard":null,"tryCatchPattern":"begin\n  data = OutcomeData::FromApi.new(options).data\nrescue Canvas::Migration::Error => e\n  Rails.logger.error(\"AB API unavailable: #{e.message}\")\nend","preventionTips":["Check AcademicBenchmark.config is non-nil and complete on boot.","Keep credentials in plugin settings across all environments.","Fall back to file-based imports when credentials are absent."],"tags":["credentials","configuration","api"],"backgroundTag":"missing-credentials","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}