Код ошибки swift t13

title description ms.custom ms.date ms.prod ms.reviewer ms.suite ms.tgt_pltfrm ms.topic ms.assetid caps.latest.revision author ms.author manager

SWIFT error codes in BizTalk Server | Microsoft Docs

View the class and validation types for the SWIFT Accelerator in BizTalk Server

08/16/2017

biztalk-server

article

03699986-965b-4a28-ab2e-09f110fb4db6

4

MandiOhlinger

mandia

anneta

SWIFT defines many network-imposed validations against the set of financial (FIN) messages. Each validation relates to a type of check against the contents of the message, and is associated with a three-character error code. The first character of the error code implies the class of the problem detected, and is a letter. The remaining two characters denote the detail of the error (when combined with the class) and always appear as a two-digit code.

Class of errors

The following table lists the letter designations, validation type, rule change associated with each class of error, and whether or not the class of error is supported.

Class Validation type and rule change Supported?
C, D, E Semantic validation rules 0-299 Supported
Knn Invalid code word in field nn Supported
M50 Message length exceeded Unsupported
M60 Non-SWIFT character encountered Supported
T Text validation error codes Supported
G Specific error codes for message user group (MUG) Textval rules Unsupported
B Special error codes for value-added services Unsupported

All SWIFT errors should be referenced in the SWIFT User Handbook. For more information and for a complete list of SWIFT error codes, refer to the Message Format Validation Rules volume of the SWIFT User Handbook. [!INCLUDEbtaA4SWIFT2.3abbrevnonumber] implements the rules in the September 2003 edition of this publication. You can access the SWIFT Web site at https://go.microsoft.com/fwlink/?LinkId=27885.

Validation errors

There are some codes which are defined by A4SWIFT. These error codes are used in the validation/network rules created and implemented by A4SWIFT, so there is no corresponding error code defined by SWIFT for such rules. Below table shows the error code and corresponding case in which the error is thrown. is the particular field which throws the error.

Error Code Description
A4SWIFT001 The first character of multiline field cannot be ‘:’ or ‘-‘ character for second and subsequent lines.
A4SWIFT002 Field contains invalid value.

[!NOTE]
[!INCLUDEA4SWIFT_CurrentVersion_FirstRef] includes support for some legacy messages, because internal applications might use these messages. Therefore, A4SWIFT maintains the associated SWIFT rules and error codes.

More good info

Troubleshooting: Issues and Resolutions
Known Issues
Common terms and definitions

title description ms.custom ms.date ms.prod ms.reviewer ms.suite ms.tgt_pltfrm ms.topic ms.assetid caps.latest.revision author ms.author manager

SWIFT error codes in BizTalk Server | Microsoft Docs

View the class and validation types for the SWIFT Accelerator in BizTalk Server

08/16/2017

biztalk-server

article

03699986-965b-4a28-ab2e-09f110fb4db6

4

MandiOhlinger

mandia

anneta

SWIFT defines many network-imposed validations against the set of financial (FIN) messages. Each validation relates to a type of check against the contents of the message, and is associated with a three-character error code. The first character of the error code implies the class of the problem detected, and is a letter. The remaining two characters denote the detail of the error (when combined with the class) and always appear as a two-digit code.

Class of errors

The following table lists the letter designations, validation type, rule change associated with each class of error, and whether or not the class of error is supported.

Class Validation type and rule change Supported?
C, D, E Semantic validation rules 0-299 Supported
Knn Invalid code word in field nn Supported
M50 Message length exceeded Unsupported
M60 Non-SWIFT character encountered Supported
T Text validation error codes Supported
G Specific error codes for message user group (MUG) Textval rules Unsupported
B Special error codes for value-added services Unsupported

All SWIFT errors should be referenced in the SWIFT User Handbook. For more information and for a complete list of SWIFT error codes, refer to the Message Format Validation Rules volume of the SWIFT User Handbook. [!INCLUDEbtaA4SWIFT2.3abbrevnonumber] implements the rules in the September 2003 edition of this publication. You can access the SWIFT Web site at https://go.microsoft.com/fwlink/?LinkId=27885.

Validation errors

There are some codes which are defined by A4SWIFT. These error codes are used in the validation/network rules created and implemented by A4SWIFT, so there is no corresponding error code defined by SWIFT for such rules. Below table shows the error code and corresponding case in which the error is thrown. is the particular field which throws the error.

Error Code Description
A4SWIFT001 The first character of multiline field cannot be ‘:’ or ‘-‘ character for second and subsequent lines.
A4SWIFT002 Field contains invalid value.

[!NOTE]
[!INCLUDEA4SWIFT_CurrentVersion_FirstRef] includes support for some legacy messages, because internal applications might use these messages. Therefore, A4SWIFT maintains the associated SWIFT rules and error codes.

More good info

Troubleshooting: Issues and Resolutions
Known Issues
Common terms and definitions

Обработка ошибок

Обработка ошибок — это процесс реагирования на возникновение ошибок и восстановление после появления ошибок в программе. Swift предоставляет первоклассную поддержку при генерации, вылавливании и переносе ошибок, устранении ошибок во время выполнения программы.

Некоторые операции не всегда гарантируют полное выполнение или конечный результат. Опционалы используются для обозначения отсутствия значения, но когда случается сбой, важно понять, что вызвало сбой, для того, чтобы соответствующим образом изменить код.

В качестве примера, рассмотрим задачу считывания и обработки данных из файла на диске. Задача может провалиться по нескольким причинам, в том числе: файл не существует по указанному пути, или файл не имеет разрешение на чтение, или файл не закодирован в необходимом формате. Отличительные особенности этих различных ситуаций позволяют программе решать некоторые ошибки самостоятельно и сообщать пользователю какие ошибки она не может решить сама.

Отображение и генерация ошибок

В Swift ошибки отображаются значениями типов, которые соответствуют протоколу Error. Этот пустой протокол является индикатором того, что это перечисление может быть использовано для обработки ошибок.

Перечисления в Swift особенно хорошо подходят для группировки схожих между собой условий возникновения ошибок и соответствующих им значений, что позволяет получить дополнительную информацию о природе самой ошибки. Например, вот как отображаются условия ошибки работы торгового автомата внутри игры:

enum VendingMachineError: Error {
    case invalidSelection
    case insufficientFunds(coinsNeeded: Int)
    case outOfStock
}

Генерация ошибки позволяет указать, что произошло что-то неожиданное и обычное выполнение программы не может продолжаться. Для того чтобы «сгенерировать» ошибку, вы используете инструкцию throw. Например, следующий код генерирует ошибку, указывая, что пять дополнительных монет нужны торговому автомату:

throw VendingMachineError.insufficientFunds(coinsNeeded: 5)

Обработка ошибок

Когда генерируется ошибка, то фрагмент кода, окружающий ошибку, должен быть ответственным за ее обработку: например, он должен исправить ее, или испробовать альтернативный подход, или просто информировать пользователя о неудачном исполнении кода.

В Swift существует четыре способа обработки ошибок. Вы можете передать (propagate) ошибку из функции в код, который вызывает саму эту функцию, обработать ошибку, используя инструкцию do-catch, обработать ошибку, как значение опционала, или можно поставить утверждение, что ошибка в данном случае исключена. Каждый вариант будет рассмотрен далее.

Когда функция генерирует ошибку, последовательность выполнения вашей программы меняется, поэтому важно сразу обнаружить место в коде, которое может генерировать ошибки. Для того, чтобы выяснить где именно это происходит, напишите ключевое слово try — или варианты try? или try!— до куска кода, вызывающего функцию, метод или инициализатор, который может генерировать ошибку. Эти ключевые слова описываются в следующем параграфе.

Заметка

Обработка ошибок в Swift напоминает обработку исключений (exceptions) в других языках, с использованием ключевых слов try, catch и throw. В отличие от обработки исключений во многих языках, в том числе и в Objective-C- обработка ошибок в Swift не включает разворачивание стека вызовов, то есть процесса, который может быть дорогим в вычислительном отношении. Таким образом, производительные характеристики инструкции throw сопоставимы с характеристиками оператора return.

Передача ошибки с помощью генерирующей функции

Чтобы указать, что функция, метод или инициализатор могут генерировать ошибку, вам нужно написать ключевое слово throws в реализации функции после ее параметров. Функция, отмеченная throws называется генерирующей функцией. Если у функции установлен возвращаемый тип, то вы пишете ключевое слово throws перед стрелкой возврата (->).

func canThrowErrors() throws -> String

func cannotThrowErrors() -> String

Генерирующая функция передает ошибки, которые возникают внутри нее в область вызова этой функции.

Заметка

Только генерирующая ошибку функция может передавать ошибки. Любые ошибки, сгенерированные внутри non-throwing функции, должны быть обработаны внутри самой функции.

В приведенном ниже примере VendingMachine класс имеет vend(itemNamed: ) метод, который генерирует соответствующую VendingMachineError, если запрошенный элемент недоступен, его нет в наличии, или имеет стоимость, превышающую текущий депозит:

struct Item {
    var price: Int
    var count: Int
}
 
class VendingMachine {
    var inventory = [
        "Candy Bar": Item(price: 12, count: 7),
        "Chips": Item(price: 10, count: 4),
        "Pretzels": Item(price: 7, count: 11)
    ]
    var coinsDeposited = 0
    
    func vend(itemNamed name: String) throws {
        guard let item = inventory[name] else {
            throw VendingMachineError.invalidSelection
        }
        
        guard item.count > 0 else {
            throw VendingMachineError.outOfStock
        }
        
        guard item.price <= coinsDeposited else {
            throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
        }
        
        coinsDeposited -= item.price
        
        var newItem = item
        newItem.count -= 1
        inventory[name] = newItem
        
        print("Dispensing (name)")
    }
}

Реализация vend(itemNamed: ) метода использует оператор guard для раннего выхода из метода и генерации соответствующих ошибок, если какое-либо требование для приобретения закуски не будет выполнено. Потому что инструкция throw мгновенно изменяет управление программой, и выбранная позиция будет куплена, только если все эти требования будут выполнены.

Поскольку vend(itemNamed: ) метод передает все ошибки, которые он генерирует, вызывающему его коду, то они должны быть обработаны напрямую, используя оператор do-catch, try? или try!, или должны быть переданы дальше. Например, buyFavoriteSnack(person:vendingMachine: ) в примере ниже — это тоже генерирующая функция, и любые ошибки, которые генерирует метод vend(itemNamed: ), будут переноситься до точки, где будет вызываться функция buyFavoriteSnack(person:vendingMachine: ).

let favoriteSnacks = [
    "Alice": "Chips",
    "Bob": "Licorice",
    "Eve": "Pretzels"
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
    let snackName = favoriteSnacks[person] ?? "Candy Bar"
    try vendingMachine.vend(itemNamed: snackName)
}

В этом примере, функция buyFavoriteSnack(person:vendingMachine: ) подбирает любимые закуски данного человека и пытается их купить, вызывая vend(itemNamed: ) метод. Поскольку метод vend(itemNamed: ) может сгенерировать ошибку, он вызывается с ключевым словом try перед ним.

Генерирующие ошибку инициализаторы могут распространять ошибки таким же образом, как генерирующие ошибку функции. Например, инициализатор структуры PurchasedSnack в списке ниже вызывает генерирующую ошибку функции как часть процесса инициализации, и он обрабатывает любые ошибки, с которыми сталкивается, путем распространения их до вызывающего его объекта.

struct PurchasedSnack {
    let name: String
    init(name: String, vendingMachine: VendingMachine) throws {
        try vendingMachine.vend(itemNamed: name)
        self.name = name
    }
}

Обработка ошибок с использованием do-catch

Используйте инструкцию do-catch для обработки ошибок, запуская блок кода. Если выдается ошибка в коде условия do, она соотносится с условием catch для определения того, кто именно сможет обработать ошибку.

Вот общий вид условия do-catch:

do {
    try выражение
    выражение
} catch шаблон 1 {
    выражение
} catch шаблон 2  where условие {
    выражение
} catch шаблон 3, шаблон 4 where условие {
    выражение
} catch {
    выражение
}

Вы пишете шаблон после ключевого слова catch, чтобы указать какие ошибки могут обрабатываться данным пунктом этого обработчика. Если условие catch не имеет своего шаблона, то оно подходит под любые ошибки и связывает ошибки к локальной константе error. Более подробно о соответствии шаблону см. Шаблоны.

Например, следующий код обрабатывает все три случая в перечислении VendingMachineError, но все другие ошибки должны быть обработаны окружающей областью:

var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
    try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
} catch VendingMachineError.invalidSelection {
    print("Ошибка выбора.")
} catch VendingMachineError.outOfStock {
    print("Нет в наличии.")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
    print("Недостаточно средств. Пожалуйста вставьте еще (coinsNeeded) монетки.")
} catch {
    print("Неожиданная ошибка: (error).")
}
// Выведет "Недостаточно средств. Пожалуйста вставьте еще 2 монетки.

В приведенном выше примере, buyFavoriteSnack(person:vendingMachine: ) функция вызывается в выражении try, потому что она может сгенерировать ошибку. Если генерируется ошибка, выполнение немедленно переносится в условия catch, которые принимают решение о продолжении передачи ошибки. Если ошибка не генерируется, остальные операторы do выполняются.

В условии catch не нужно обрабатывать все возможные ошибки, которые может вызвать код в условии do. Если ни одно из условий catch не обрабатывает ошибку, ошибка распространяется на окружающую область. Однако распространяемая ошибка должна обрабатываться некоторой внешней областью. В функции nonthrowing условие включения do-catch должно обрабатывать ошибку. В функции throwing либо включающая условие do-catch, либо вызывающая сторона должна обрабатывать ошибку. Если ошибка распространяется на область верхнего уровня без обработки, вы получите ошибку исполнения.

Например, приведенный ниже пример можно записать так, чтобы любая ошибка, которая не является VendingMachineError, вместо этого захватывалась вызывающей функцией:

func nourish(with item: String) throws {
    do {
        try vendingMachine.vend(itemNamed: item)
    } catch is VendingMachineError {
        print("Некорректный вывод, нет в наличии или недостаточно денег.")
    }
}

do {
    try nourish(with: "Beet-Flavored Chips")
} catch {
    print("Unexpected non-vending-machine-related error: (error)")
}
// Выведет "Некорректный вывод, нет в наличии или недостаточно денег."

В nourish(with: ), если vend(itemNamed : ) выдает ошибку, которая является одним из кейсов перечисления VendingMachineError, nourish(with: ) обрабатывает ошибку, печатая сообщение. В противном случае, nourish(with: ) распространяет ошибку на свое место вызова. Ошибка затем попадает в общее условие catch.

Преобразование ошибок в опциональные значения

Вы можете использовать try? для обработки ошибки, преобразовав ее в опциональное значение. Если ошибка генерируется при условии try?, то значение выражения вычисляется как nil. Например, в следующем коде x и y имеют одинаковые значения и поведение:

func someThrowingFunction() throws -> Int {
    // ...
}
 
let x = try? someThrowingFunction()
 
let y: Int?
do {
    y = try someThrowingFunction()
} catch {
    y = nil
}

Если someThrowingFunction() генерирует ошибку, значение x и y равно nil. В противном случае значение x и y — это возвращаемое значение функции. Обратите внимание, что x и y являются опциональными, независимо от того какой тип возвращает функция someThrowingFunction().

Использование try? позволяет написать краткий код обработки ошибок, если вы хотите обрабатывать все ошибки таким же образом. Например, следующий код использует несколько попыток для извлечения данных или возвращает nil, если попытки неудачные.

func fetchData() -> Data? {
    if let data = try? fetchDataFromDisk() { return data }
    if let data = try? fetchDataFromServer() { return data }
    return nil
}

Запрет на передачу ошибок

Иногда вы знаете, что функции throw или методы не сгенерируют ошибку во время исполнения. В этих случаях, вы можете написать try! перед выражением для запрета передачи ошибки и завернуть вызов в утверждение того, что ошибка точно не будет сгенерирована. Если ошибка на самом деле сгенерирована, вы получите сообщение об ошибке исполнения.

Например, следующий код использует loadImage(atPath: ) функцию, которая загружает ресурс изображения по заданному пути или генерирует ошибку, если изображение не может быть загружено. В этом случае, поскольку изображение идет вместе с приложением, сообщение об ошибке не будет сгенерировано во время выполнения, поэтому целесообразно отключить передачу ошибки.

let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")

Установка действий по очистке (Cleanup)

Вы используете оператор defer для выполнения набора инструкций перед тем как исполнение кода оставит текущий блок. Это позволяет сделать любую необходимую очистку, которая должна быть выполнена, независимо от того, как именно это произойдет — либо он покинет из-за сгенерированной ошибки или из-за оператора, такого как break или return. Например, вы можете использовать defer, чтобы удостовериться, что файл дескрипторов закрыт и выделенная память вручную освобождена.

Оператор defer откладывает выполнение, пока не происходит выход из текущей области. Этот оператор состоит из ключевого слова defer и выражений, которые должны быть выполнены позже. Отложенные выражения могут не содержать кода, изменяющего контроль исполнения изнутри наружу, при помощи таких операторов как break или return, или просто генерирующего ошибку. Отложенные действия выполняются в обратном порядке, как они указаны, то есть, код в первом операторе defer выполняется после кода второго, и так далее.

func processFile(filename: String) throws {
    if exists(filename) {
        let file = open(filename)
        defer {
            close(file)
        }
        while let line = try file.readline() {
            // работаем с файлом.
        }
        // close(file) вызывается здесь, в конце зоны видимости.
    }
}

Приведенный выше пример использует оператор defer, чтобы удостовериться, что функция open(_: ) имеет соответствующий вызов и для close(_: ).

Заметка

Вы можете использовать оператор defer, даже если не используете кода обработки ошибок.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Обработка ошибок — это процесс реагирования и исправления ошибок в вашей программе. Swift обеспечивает первоклассную поддержку для генерации, перехвата, распространения и обработки исправляемых ошибок во время выполнения.

Некоторые операции не всегда гарантируют завершение выполнения или получение полезного результата. Необязательные параметры используются для представления отсутствия значения, но когда происходит сбой операции, часто полезно понять, что вызвало сбой, чтобы ваш код мог реагировать соответствующим образом.

В качестве примера рассмотрим задачу чтения и обработки данных из файла на диске. Эта задача может быть выполнена несколькими способами, включая файл, не существующий по указанному пути, файл, не имеющий разрешений на чтение, или файл, не закодированный в совместимом формате. Различение между этими различными ситуациями позволяет программе устранять некоторые ошибки и сообщать пользователю о любых ошибках, которые она не может устранить.

ЗАМЕТКА

Обработка ошибок в Swift взаимодействует с шаблонами обработки ошибок, которые используют NSErrorкласс в Какао и Objective-C. 

Представление и бросание ошибок

В Swift ошибки представлены значениями типов, которые соответствуют Errorпротоколу. Этот пустой протокол указывает, что тип может использоваться для обработки ошибок.

Перечисления Swift особенно хорошо подходят для моделирования группы связанных состояний ошибок с соответствующими значениями, позволяющими передавать дополнительную информацию о природе ошибки. Например, вот как вы можете представить условия ошибки работы торгового автомата в игре:

enum VendingMachineError: Error {
    case invalidSelection
    case insufficientFunds(coinsNeeded: Int)
    case outOfStock
}

Выдача ошибки позволяет вам указать, что произошло что-то неожиданное, и нормальный поток выполнения не может продолжаться. Вы используете throwзаявление, чтобы выбросить ошибку. Например, следующий код выдает ошибку, чтобы указать, что торговому автомату необходимо пять дополнительных монет:

throw VendingMachineError.insufficientFunds(coinsNeeded: 5)

Обработка ошибок

Когда выдается ошибка, некоторый окружающий фрагмент кода должен отвечать за обработку ошибки — например, путем исправления проблемы, попытки альтернативного подхода или информирования пользователя о сбое.

Существует четыре способа обработки ошибок в Swift. Вы можете распространять ошибку из функции в код, который вызывает эту функцию, обрабатывать ошибку с помощью оператора do— catch, обрабатывать ошибку как необязательное значение или утверждать, что ошибка не произойдет. Каждый подход описан в разделе ниже.

Когда функция выдает ошибку, она меняет поток вашей программы, поэтому важно, чтобы вы могли быстро определить места в вашем коде, которые могут выдавать ошибки. Чтобы определить эти места в вашем коде, напишите tryключевое слово ( try?или try!вариант или) перед фрагментом кода, который вызывает функцию, метод или инициализатор, который может вызвать ошибку. Эти ключевые слова описаны в разделах ниже.

ЗАМЕТКА

Обработка ошибок в Swift напоминает обработку исключений в других языках, с использованием trycatchи throwключевых слов. В отличие от обработки исключений во многих языках, включая Objective-C, обработка ошибок в Swift не включает в себя разматывание стека вызовов, процесс, который может быть вычислительно дорогим. Таким образом, рабочие характеристики throwоператора сопоставимы с характеристиками returnоператора.

Распространение ошибок с использованием бросающих функций

Чтобы указать, что функция, метод или инициализатор могут выдать ошибку, вы пишете throwsключевое слово в объявлении функции после ее параметров. Функция с пометкой throwsназывается функцией броска . Если функция указывает тип возвращаемого значения, вы пишете throwsключевое слово перед стрелкой возврата ( ->).

func canThrowErrors() throws -> String

func cannotThrowErrors() -> String

Функция выброса распространяет ошибки, которые выбрасываются внутри нее, в область, из которой она вызывается.

ЗАМЕТКА

Только бросающие функции могут распространять ошибки. Любые ошибки, возникающие в неработающей функции, должны обрабатываться внутри функции.

В приведенном ниже примере VendingMachineкласс имеет vend(itemNamed:)метод, который выбрасывает соответствующее значение, VendingMachineErrorесли запрошенный элемент недоступен, отсутствует на складе или имеет стоимость, превышающую текущую сумму депозита:

struct Item {
    var price: Int
    var count: Int
}
 
class VendingMachine {
    var inventory = [
        "Candy Bar": Item(price: 12, count: 7),
        "Chips": Item(price: 10, count: 4),
        "Pretzels": Item(price: 7, count: 11)
    ]
    var coinsDeposited = 0
    
    func vend(itemNamed name: String) throws {
        guard let item = inventory[name] else {
            throw VendingMachineError.invalidSelection
        }
        
        guard item.count > 0 else {
            throw VendingMachineError.outOfStock
        }
        
        guard item.price <= coinsDeposited else {
            throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
        }
        
        coinsDeposited -= item.price
        
        var newItem = item
        newItem.count -= 1
        inventory[name] = newItem
        
        print("Dispensing (name)")
    }
}

Реализация vend(itemNamed:)метода использует guardоператоры для раннего выхода из метода и выдачи соответствующих ошибок, если какое-либо из требований для покупки закуски не выполнено. Поскольку throwоператор немедленно передает управление программой, элемент будет продаваться, только если все эти требования будут выполнены.

Поскольку vend(itemNamed:)метод распространяется любые ошибки , он бросает, любой код , который вызывает этот метод должен либо обрабатывать ошибки, используя do— catchзаявление, try?или try!-или продолжают их распространять. Например, buyFavoriteSnack(person:vendingMachine:)в приведенном ниже примере также есть функция throwing, и любые ошибки, которые vend(itemNamed:)генерирует метод, будут распространяться вплоть до точки, где buyFavoriteSnack(person:vendingMachine:)вызывается функция.

let favoriteSnacks = [

"Alice": "Chips",

"Bob": "Licorice",

"Eve": "Pretzels",

]

func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {

let snackName = favoriteSnacks[person] ?? "Candy Bar"

try vendingMachine.vend(itemNamed: snackName)

}

В этом примере функция ищет любимую закуску данного человека и пытается купить ее, вызвав метод. Поскольку метод может выдать ошибку, он вызывается с ключевым словом перед ним.buyFavoriteSnack(person: vendingMachine:)vend(itemNamed:)vend(itemNamed:)try

Бросающие инициализаторы могут распространять ошибки так же, как и бросающие функции. Например, инициализатор для PurchasedSnackструктуры в приведенном ниже листинге вызывает функцию выброса как часть процесса инициализации и обрабатывает любые возникающие ошибки, передавая их вызывающей стороне.

struct PurchasedSnack {

let name: String

init(name: String, vendingMachine: VendingMachine) throws {

try vendingMachine.vend(itemNamed: name)

self.name = name

}

}

Обработка ошибок с помощью Do-Catch

Вы используете оператор do— catchдля обработки ошибок, выполняя блок кода. Если код в doпредложении выдает ошибку , он сопоставляется с catchпредложениями, чтобы определить, какой из них может обработать ошибку.

Вот общая форма do— catchзаявление:

do {

try expression

statements

} catch pattern 1 {

statements

} catch pattern 2 where condition {

statements

} catch {

statements

}

Вы пишете шаблон после, catchчтобы указать, какие ошибки может обработать это предложение. Если catchпредложение не имеет шаблона, оно сопоставляется с любой ошибкой и связывает ошибку с локальной константой с именем error

Например, следующий код соответствует всем трем случаям VendingMachineErrorперечисления.

var vendingMachine = VendingMachine()

vendingMachine.coinsDeposited = 8

do {

try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)

print("Success! Yum.")

} catch VendingMachineError.invalidSelection {

print("Invalid Selection.")

} catch VendingMachineError.outOfStock {

print("Out of Stock.")

} catch VendingMachineError.insufficientFunds(let coinsNeeded) {

print("Insufficient funds. Please insert an additional (coinsNeeded) coins.")

} catch {

print("Unexpected error: (error).")

}

// Prints "Insufficient funds. Please insert an additional 2 coins."

В приведенном выше примере buyFavoriteSnack(person:vendingMachine:)функция вызывается в tryвыражении, поскольку она может выдать ошибку. Если выдается ошибка, выполнение немедленно переходит к catchпредложениям, которые решают, следует ли продолжить распространение. Если ни один шаблон не сопоставлен, ошибка попадает в заключительное catchпредложение и связывается с локальной errorконстантой. Если ошибка не выдана, остальные операторы в doоператоре выполняются.

Предложения catchне должны обрабатывать каждую возможную ошибку, которую doможет выдать код в предложении. Если ни одно из catchпредложений не обрабатывает ошибку, ошибка распространяется на окружающую область. Однако распространяемая ошибка должна быть обработана некоторой окружающей областью. В функции nonthrowing, объемлющий do— catchпункт должен обработать ошибку. В функции метательного, либо вшита do— catchпункт или вызывающий должен обработать ошибку. Если ошибка распространяется на область верхнего уровня без обработки, вы получите ошибку во время выполнения.

Например, приведенный выше пример может быть написан так, что любая ошибка, которая не VendingMachineErrorявляется, вместо этого перехватывается вызывающей функцией:

func nourish(with item: String) throws {

do {

try vendingMachine.vend(itemNamed: item)

} catch is VendingMachineError {

print("Invalid selection, out of stock, or not enough money.")

}

}



do {

try nourish(with: "Beet-Flavored Chips")

} catch {

print("Unexpected non-vending-machine-related error: (error)")

}

// Prints "Invalid selection, out of stock, or not enough money."

В nourish(with:)функции, если vend(itemNamed:)выдает ошибку, которая является одним из случаев VendingMachineErrorперечисления, nourish(with:)обрабатывает ошибку, печатая сообщение. В противном случае nourish(with:)распространяет ошибку на свой сайт вызова. Ошибка тогда поймана общим catchпредложением.

Преобразование ошибок в необязательные значения

Вы используете try?для обработки ошибки путем преобразования ее в необязательное значение. Если при вычислении try?выражения выдается ошибка , значением выражения является nil. Например, в следующем коде xи yимеют то же значение и поведение:

func someThrowingFunction() throws -> Int {
    // ...
}
 
let x = try? someThrowingFunction()
 
let y: Int?
do {
    y = try someThrowingFunction()
} catch {
    y = nil
}

Если someThrowingFunction()выдает ошибку, значение xи yесть nil. В противном случае значение xи yявляется значением, которое вернула функция. Обратите внимание, что xи yявляются необязательными для любого типа someThrowingFunction()возврата. Здесь функция возвращает целое число, поэтому xи yявляются необязательными целыми числами.

Использование try?позволяет вам написать краткий код обработки ошибок, когда вы хотите обрабатывать все ошибки одинаково. Например, следующий код использует несколько подходов для извлечения данных или возвращает, nilесли все подходы дают сбой.

func fetchData() -> Data? {

if let data = try? fetchDataFromDisk() { return data }

if let data = try? fetchDataFromServer() { return data }

return nil

}

Отключение распространения ошибок

Иногда вы знаете, что бросающая функция или метод на самом деле не будут выдавать ошибку во время выполнения. В таких случаях вы можете написать try!перед выражением, чтобы отключить распространение ошибок, и обернуть вызов в утверждение времени выполнения, что не будет выдано никакой ошибки. Если на самом деле выдается ошибка, вы получите ошибку во время выполнения.

Например, в следующем коде используется loadImage(atPath:)функция, которая загружает ресурс изображения по заданному пути или выдает ошибку, если изображение не может быть загружено. В этом случае, поскольку образ поставляется с приложением, во время выполнения не будет выдано никаких ошибок, поэтому целесообразно отключить распространение ошибок.

let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")

Указание действий по очистке

Вы используете deferоператор для выполнения набора операторов непосредственно перед тем, как выполнение кода покидает текущий блок кода. Этот оператор позволяет выполнять любую необходимую очистку, которая должна выполняться независимо от того, как выполнение покидает текущий блок кода — независимо от того, была ли вызвана ошибка или из-за оператора, такого как returnили break. Например, вы можете использовать deferинструкцию, чтобы гарантировать, что файловые дескрипторы закрыты, а выделенная вручную память освобождена.

deferЗаявление отсрочивает выполнение , пока текущая область не закрывается. Этот оператор состоит из deferключевого слова и операторов, которые будут выполнены позже. Отложенные операторы могут не содержать какой-либо код, который передавал бы управление из операторов, таких как оператор a breakили return, или путем выдачи ошибки. Отложенные действия выполняются в порядке, обратном порядку их написания в исходном коде. То есть код в первом deferоператоре выполняется последним, код во втором deferоператоре выполняется со второго до последнего и так далее. Последний deferоператор в порядке исходного кода выполняется первым.

func processFile(filename: String) throws {

if exists(filename) {

let file = open(filename)

defer {

close(file)

}

while let line = try file.readline() {

// Work with the file.

}

// close(file) is called here, at the end of the scope.

}

}

В приведенном выше примере используется deferоператор, чтобы гарантировать, что open(_:)функция имеет соответствующий вызов close(_:).

ЗАМЕТКА

Вы можете использовать deferоператор, даже если код обработки ошибок не используется.

Error handling is the process of responding to and recovering from error conditions in your program. Swift provides first-class support for throwing, catching, propagating, and manipulating recoverable errors at runtime.

Some operations aren’t guaranteed to always complete execution or produce a useful output. Optionals are used to represent the absence of a value, but when an operation fails, it’s often useful to understand what caused the failure, so that your code can respond accordingly.

As an example, consider the task of reading and processing data from a file on disk. There are a number of ways this task can fail, including the file not existing at the specified path, the file not having read permissions, or the file not being encoded in a compatible format. Distinguishing among these different situations allows a program to resolve some errors and to communicate to the user any errors it can’t resolve.

Representing and Throwing Errors¶

In Swift, errors are represented by values of types that conform to the Error protocol. This empty protocol indicates that a type can be used for error handling.

Swift enumerations are particularly well suited to modeling a group of related error conditions, with associated values allowing for additional information about the nature of an error to be communicated. For example, here’s how you might represent the error conditions of operating a vending machine inside a game:

  1. enum VendingMachineError: Error {
  2. case invalidSelection
  3. case insufficientFunds(coinsNeeded: Int)
  4. case outOfStock
  5. }

Throwing an error lets you indicate that something unexpected happened and the normal flow of execution can’t continue. You use a throw statement to throw an error. For example, the following code throws an error to indicate that five additional coins are needed by the vending machine:

  1. throw VendingMachineError.insufficientFunds(coinsNeeded: 5)

Handling Errors¶

When an error is thrown, some surrounding piece of code must be responsible for handling the error—for example, by correcting the problem, trying an alternative approach, or informing the user of the failure.

There are four ways to handle errors in Swift. You can propagate the error from a function to the code that calls that function, handle the error using a docatch statement, handle the error as an optional value, or assert that the error will not occur. Each approach is described in a section below.

When a function throws an error, it changes the flow of your program, so it’s important that you can quickly identify places in your code that can throw errors. To identify these places in your code, write the try keyword—or the try? or try! variation—before a piece of code that calls a function, method, or initializer that can throw an error. These keywords are described in the sections below.

Note

Error handling in Swift resembles exception handling in other languages, with the use of the try, catch and throw keywords. Unlike exception handling in many languages—including Objective-C—error handling in Swift doesn’t involve unwinding the call stack, a process that can be computationally expensive. As such, the performance characteristics of a throw statement are comparable to those of a return statement.

Propagating Errors Using Throwing Functions¶

To indicate that a function, method, or initializer can throw an error, you write the throws keyword in the function’s declaration after its parameters. A function marked with throws is called a throwing function. If the function specifies a return type, you write the throws keyword before the return arrow (->).

  1. func canThrowErrors() throws -> String
  2. func cannotThrowErrors() -> String

A throwing function propagates errors that are thrown inside of it to the scope from which it’s called.

Note

Only throwing functions can propagate errors. Any errors thrown inside a nonthrowing function must be handled inside the function.

In the example below, the VendingMachine class has a vend(itemNamed:) method that throws an appropriate VendingMachineError if the requested item isn’t available, is out of stock, or has a cost that exceeds the current deposited amount:

  1. struct Item {
  2. var price: Int
  3. var count: Int
  4. }
  5. class VendingMachine {
  6. var inventory = [
  7. «Candy Bar»: Item(price: 12, count: 7),
  8. «Chips»: Item(price: 10, count: 4),
  9. «Pretzels»: Item(price: 7, count: 11)
  10. ]
  11. var coinsDeposited = 0
  12. func vend(itemNamed name: String) throws {
  13. guard let item = inventory[name] else {
  14. throw VendingMachineError.invalidSelection
  15. }
  16. guard item.count > 0 else {
  17. throw VendingMachineError.outOfStock
  18. }
  19. guard item.price <= coinsDeposited else {
  20. throw VendingMachineError.insufficientFunds(coinsNeeded: item.pricecoinsDeposited)
  21. }
  22. coinsDeposited -= item.price
  23. var newItem = item
  24. newItem.count -= 1
  25. inventory[name] = newItem
  26. print(«Dispensing (name)«)
  27. }
  28. }

The implementation of the vend(itemNamed:) method uses guard statements to exit the method early and throw appropriate errors if any of the requirements for purchasing a snack aren’t met. Because a throw statement immediately transfers program control, an item will be vended only if all of these requirements are met.

Because the vend(itemNamed:) method propagates any errors it throws, any code that calls this method must either handle the errors—using a docatch statement, try?, or try!—or continue to propagate them. For example, the buyFavoriteSnack(person:vendingMachine:) in the example below is also a throwing function, and any errors that the vend(itemNamed:) method throws will propagate up to the point where the buyFavoriteSnack(person:vendingMachine:) function is called.

  1. let favoriteSnacks = [
  2. «Alice»: «Chips»,
  3. «Bob»: «Licorice»,
  4. «Eve»: «Pretzels»,
  5. ]
  6. func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
  7. let snackName = favoriteSnacks[person] ?? «Candy Bar»
  8. try vendingMachine.vend(itemNamed: snackName)
  9. }

In this example, the buyFavoriteSnack(person: vendingMachine:) function looks up a given person’s favorite snack and tries to buy it for them by calling the vend(itemNamed:) method. Because the vend(itemNamed:) method can throw an error, it’s called with the try keyword in front of it.

Throwing initializers can propagate errors in the same way as throwing functions. For example, the initializer for the PurchasedSnack structure in the listing below calls a throwing function as part of the initialization process, and it handles any errors that it encounters by propagating them to its caller.

  1. struct PurchasedSnack {
  2. let name: String
  3. init(name: String, vendingMachine: VendingMachine) throws {
  4. try vendingMachine.vend(itemNamed: name)
  5. self.name = name
  6. }
  7. }

Handling Errors Using Do-Catch¶

You use a docatch statement to handle errors by running a block of code. If an error is thrown by the code in the do clause, it’s matched against the catch clauses to determine which one of them can handle the error.

Here is the general form of a docatch statement:

  1. do {
  2. try expression
  3. statements
  4. } catch pattern 1 {
  5. statements
  6. } catch pattern 2 where condition {
  7. statements
  8. } catch pattern 3, pattern 4 where condition {
  9. statements
  10. } catch {
  11. statements
  12. }

You write a pattern after catch to indicate what errors that clause can handle. If a catch clause doesn’t have a pattern, the clause matches any error and binds the error to a local constant named error. For more information about pattern matching, see Patterns.

For example, the following code matches against all three cases of the VendingMachineError enumeration.

  1. var vendingMachine = VendingMachine()
  2. vendingMachine.coinsDeposited = 8
  3. do {
  4. try buyFavoriteSnack(person: «Alice», vendingMachine: vendingMachine)
  5. print(«Success! Yum.»)
  6. } catch VendingMachineError.invalidSelection {
  7. print(«Invalid Selection.»)
  8. } catch VendingMachineError.outOfStock {
  9. print(«Out of Stock.»)
  10. } catch VendingMachineError.insufficientFunds(let coinsNeeded) {
  11. print(«Insufficient funds. Please insert an additional (coinsNeeded) coins.»)
  12. } catch {
  13. print(«Unexpected error: (error))
  14. }
  15. // Prints «Insufficient funds. Please insert an additional 2 coins.»

In the above example, the buyFavoriteSnack(person:vendingMachine:) function is called in a try expression, because it can throw an error. If an error is thrown, execution immediately transfers to the catch clauses, which decide whether to allow propagation to continue. If no pattern is matched, the error gets caught by the final catch clause and is bound to a local error constant. If no error is thrown, the remaining statements in the do statement are executed.

The catch clauses don’t have to handle every possible error that the code in the do clause can throw. If none of the catch clauses handle the error, the error propagates to the surrounding scope. However, the propagated error must be handled by some surrounding scope. In a nonthrowing function, an enclosing docatch statement must handle the error. In a throwing function, either an enclosing docatch statement or the caller must handle the error. If the error propagates to the top-level scope without being handled, you’ll get a runtime error.

For example, the above example can be written so any error that isn’t a VendingMachineError is instead caught by the calling function:

  1. func nourish(with item: String) throws {
  2. do {
  3. try vendingMachine.vend(itemNamed: item)
  4. } catch is VendingMachineError {
  5. print(«Couldn’t buy that from the vending machine.»)
  6. }
  7. }
  8. do {
  9. try nourish(with: «Beet-Flavored Chips»)
  10. } catch {
  11. print(«Unexpected non-vending-machine-related error: (error)«)
  12. }
  13. // Prints «Couldn’t buy that from the vending machine.»

In the nourish(with:) function, if vend(itemNamed:) throws an error that’s one of the cases of the VendingMachineError enumeration, nourish(with:) handles the error by printing a message. Otherwise, nourish(with:) propagates the error to its call site. The error is then caught by the general catch clause.

Another way to catch several related errors is to list them after catch, separated by commas. For example:

  1. func eat(item: String) throws {
  2. do {
  3. try vendingMachine.vend(itemNamed: item)
  4. } catch VendingMachineError.invalidSelection, VendingMachineError.insufficientFunds, VendingMachineError.outOfStock {
  5. print(«Invalid selection, out of stock, or not enough money.»)
  6. }
  7. }

The eat(item:) function lists the vending machine errors to catch, and its error text corresponds to the items in that list. If any of the three listed errors are thrown, this catch clause handles them by printing a message. Any other errors are propagated to the surrounding scope, including any vending-machine errors that might be added later.

Converting Errors to Optional Values¶

You use try? to handle an error by converting it to an optional value. If an error is thrown while evaluating the try? expression, the value of the expression is nil. For example, in the following code x and y have the same value and behavior:

  1. func someThrowingFunction() throws -> Int {
  2. // …
  3. }
  4. let x = try? someThrowingFunction()
  5. let y: Int?
  6. do {
  7. y = try someThrowingFunction()
  8. } catch {
  9. y = nil
  10. }

If someThrowingFunction() throws an error, the value of x and y is nil. Otherwise, the value of x and y is the value that the function returned. Note that x and y are an optional of whatever type someThrowingFunction() returns. Here the function returns an integer, so x and y are optional integers.

Using try? lets you write concise error handling code when you want to handle all errors in the same way. For example, the following code uses several approaches to fetch data, or returns nil if all of the approaches fail.

  1. func fetchData() -> Data? {
  2. if let data = try? fetchDataFromDisk() { return data }
  3. if let data = try? fetchDataFromServer() { return data }
  4. return nil
  5. }

Disabling Error Propagation¶

Sometimes you know a throwing function or method won’t, in fact, throw an error at runtime. On those occasions, you can write try! before the expression to disable error propagation and wrap the call in a runtime assertion that no error will be thrown. If an error actually is thrown, you’ll get a runtime error.

For example, the following code uses a loadImage(atPath:) function, which loads the image resource at a given path or throws an error if the image can’t be loaded. In this case, because the image is shipped with the application, no error will be thrown at runtime, so it’s appropriate to disable error propagation.

  1. let photo = try! loadImage(atPath: «./Resources/John Appleseed.jpg»)

Specifying Cleanup Actions¶

You use a defer statement to execute a set of statements just before code execution leaves the current block of code. This statement lets you do any necessary cleanup that should be performed regardless of how execution leaves the current block of code—whether it leaves because an error was thrown or because of a statement such as return or break. For example, you can use a defer statement to ensure that file descriptors are closed and manually allocated memory is freed.

A defer statement defers execution until the current scope is exited. This statement consists of the defer keyword and the statements to be executed later. The deferred statements may not contain any code that would transfer control out of the statements, such as a break or a return statement, or by throwing an error. Deferred actions are executed in the reverse of the order that they’re written in your source code. That is, the code in the first defer statement executes last, the code in the second defer statement executes second to last, and so on. The last defer statement in source code order executes first.

  1. func processFile(filename: String) throws {
  2. if exists(filename) {
  3. let file = open(filename)
  4. defer {
  5. close(file)
  6. }
  7. while let line = try file.readline() {
  8. // Work with the file.
  9. }
  10. // close(file) is called here, at the end of the scope.
  11. }
  12. }

The above example uses a defer statement to ensure that the open(_:) function has a corresponding call to close(_:).

Note

You can use a defer statement even when no error handling code is involved.

Мы используем обработку ошибок с помощью do-try-catch для реагирования на исправимые ошибки. Это дает нам больший контроль над различными ошибочными сценариями, которые могут возникнуть в нашем коде, например, при вводе неправильного имени пользователя или пароля.

Зачем нужно отслеживать ошибки?

В приложении некоторые ошибки могут быть результатом ошибок программиста. Когда ваше приложение вылетает с сообщением «Index out of bounds», вы, вероятно, где-то допустили ошибку. И точно так же, когда вы принудительно извлекаете опциональное значение, которое имеет значение nil, ваше приложение падает.

В практической разработке iOS некоторые ошибки являются частью работы приложения, например, сообщение «Недостаточно средств» при попытке оплаты с помощью карты.

Ошибки такого рода исправимы. Их можно обработать и отреагировать соответствующим образом. К примеру:

  • При попытке снять деньги в банкомате отображается «Неверный PIN-код».
  • Ваш автомобиль показывает индикатор низкого уровня топлива при попытке запустить двигатель.
  • Попытка аутентификации для API возвращает «Неверное имя пользователя / пароль».

Вы можете работать с этими ошибками, отобразив сообщение с предупреждением или сделав что-то еще. Например, ваша карта блокируется после 3 неудачных попыток. Ваш автомобиль может указать вам ближайшую заправку, когда у вас кончается бензин. Вы можете попробовать ввести другое имя пользователя и пароль.

Swift поддерживает обработку ошибок с помощью блока кода do-try-catch.

Выбрасывание ошибок

Когда в вашем коде возникает сценарий, который может привести к ошибке, вы можете выбросить ошибку:

if fuel < 1000 {
    throw RocketError.insufficientFuel
}

В приведенном выше коде ключевое слово throw используется для выдачи ошибки типа RocketError.insufficientFuel, когда переменная fuel меньше, чем 1000.

Представьте, что мы пытаемся запустить ракету:

func igniteRockets(fuel: Int, astronauts: Int) throws {
    if fuel < 1000 {
        throw RocketError.insufficientFuel
    }
    else if astronauts < 3 {
        throw RocketError.insufficientAstronauts(needed: 3)
    }
 
    // Запуск ракеты
    print("3... 2... 1... Старт!")
}

Функция igniteRockets(fuel:astronauts:) будет запускать ракеты, только если значение fuel больше или равно 1000 и если на борту есть как минимум 3 астронавта.

Функция igniteRockets(…) также помечается ключевым словом throws. Это ключевое слово указывает, что ошибки должны быть обработаны.

В приведенном выше коде мы используем тип ошибки RocketError:

enum RocketError: Error {
    case insufficientFuel
    case insufficientAstronauts(needed: Int)
    case unknownError
}

Данное перечисление определяет три типа ошибок: .insufficientFuel, insufficientAstronauts(needed) и .unknownError. Определение ваших собственных типов ошибок полезно, потому что это поможет четко понять, что эти ошибки означают в вашем коде.

Возьмем, например, ошибку insufficientAstronauts(needed:). Когда выдается эта ошибка, вы можете использовать аргумент needed:, который указывает, сколько астронавтов необходимо для успешного запуска ракеты.

Ключевое слово throw имеет тот же эффект, что и ключевое слово return. Когда выполняется throw, выполнение функции останавливается, и выброшенная ошибка передается вызывающей функции.

Теперь мы можем использовать обработку ошибок, чтобы соответствующим образом реагировать на сценарии ошибок. Обработка ошибок в Swift осуществляется с помощью блока кода do-try-catch:

do {
    try igniteRockets(fuel: 5000, astronauts: 1)    
} catch {
    print(error)
}

Обработка ошибок имеет три аспекта:

  • К функции, которая может вызвать ошибку, добавляется ключевое слово try.
  • Блок кода, который включает ключевое слово try, обернут в do { … }.
  • Один или несколько блоков catch { … } могут быть присоединены к do { … } для обработки отдельных случаев ошибок.

Если функция выдает ошибку, вызывается блок catch. В данном случае это выводит ошибку на консоль.

Вы также можете реагировать на ошибки в индивидуальном порядке:

do {
    try igniteRockets(fuel: 5000, astronauts: 1)    
} catch RocketError.insufficientFuel {
    print("Ракете нужно больше топлива!")
} catch RocketError.insufficientAstronauts(let needed) {
    print("Нужно как минимум (needed) астронавта...")
}

Вышеуказанные блоки catch вызываются на основании отдельных перечислений RocketError. Вы можете напрямую получить доступ к связанным значениям перечислений, таких как needed. Также вы можете использовать выражения с шаблоном where чтобы получить больший контроль над ошибочным сценарием.

enum RocketError: Error {
    case insufficientFuel
    case insufficientAstronauts(needed: Int)
    case unknownError
}
 
func igniteRockets(fuel: Int, astronauts: Int) throws {
    if fuel < 1000 {
        throw RocketError.insufficientFuel
    }
    else if astronauts < 3 {
        throw RocketError.insufficientAstronauts(needed: 3)
    }
 
    // Ignite rockets
    print("3... 2... 1... Полет!")
}
 
do {
    try igniteRockets(fuel: 5000, astronauts: 1)
} catch {
    print(error)
}

Преобразование ошибок в опционалы с помощью try?

Целью обработки ошибок является явное определение того, что происходит при возникновении ошибки. Это позволяет нам реагировать определенным образом на ошибки.

В некоторых случаях нас не волнует сама ошибка. Нам просто нужно получить значение из функции. И если возникает ошибка, мы можем возвратить nil. Эта возможность доступна с помощью ключевого слова try? Когда вы используете try?, вам не нужно использовать полный блок кода do-try-catch.

let result = try? calculateValue(for: 42)

Представьте, что функция может выбрасывать ошибки, если ее параметр недействителен. Вместо обработки ошибки мы конвертируем возвращаемое значение в опциональное.

Возможны два сценария:

  • Функция не выдает ошибку и возвращает значение, которое присваивается константе result.
  • Функция выдает ошибку и не возвращает значение. Это означает, что константе result присваивается nil.

Обработка ошибок с помощью try? означает, что вы можете воспользоваться синтаксисом, специфичным для опционалов, таких как объединение по nil и опциональное связывание:

if let result = try? calculateValue(for: 99) {
    // 
}
 
let result = try? calculateValue(for: 123) ?? 101

Отключение обработки ошибок с помощью try!

Вы можете полностью отключить обработку ошибок с помощью try!. Ключевое слово try! используется для принудиального извлечения опционального значения.

В отличие от того try?, который возвращает опциональное значение, синтаксис try! приведет к сбою вашего кода в случае возникновения ошибки. Есть два различных сценария, в которых использование try! может быть полезно:

  • Используйте try!, когда вы на 100% уверенны, что ошибка не возникнет.
  • Используйте, try!, когда невозможно продолжить выполнение кода.

Представьте, что вы пишите приложение, в которое встроен файл базы данных. Функция загрузки базы данных выдает ошибку, когда база данных повреждена. Вы можете использовать try! для загрузки базы данных в память, потому что, если база данных повреждена, приложение все равно не сможет быть использовано.

Error Handling in Swift 2.0

As a tentpole feature for Swift 2.0, we are introducing a new
first-class error handling model. This feature provides standardized
syntax and language affordances for throwing, propagating, catching, and
manipulating recoverable error conditions.

Error handling is a well-trod path, with many different approaches in
other languages, many of them problematic in various ways. We believe
that our approach provides an elegant solution, drawing on the lessons
we’ve learned from other languages and fixing or avoiding some of the
pitfalls. The result is expressive and concise while still feeling
explicit, safe, and familiar; and we believe it will work beautifully
with the Cocoa APIs.

We’re intentionally not using the term «exception handling», which
carries a lot of connotations from its use in other languages. Our
proposal has some similarities to the exceptions systems in those
languages, but it also has a lot of important differences.

Kinds of Error

What exactly is an «error»? There are many possible error conditions,
and they don’t all make sense to handle in exactly the same way,
because they arise in different circumstances and programmers have to
react to them differently.

We can break errors down into four categories, in increasing order of
severity:

A simple domain error arises from an operation that can fail in some
obvious way and which is often invoked speculatively. Parsing an integer
from a string is a really good example. The client doesn’t need a
detailed description of the error and will usually want to handle the
error immediately. These errors are already well-modeled by returning an
optional value; we don’t need a more complex language solution for
them.

A recoverable error arises from an operation which can fail in
complex ways, but whose errors can be reasonably anticipated in advance.
Examples including opening a file or reading from a network connection.
These are the kinds of errors that Apple’s APIs use NSError for today,
but there are close analogues in many other APIs, such as errno in
POSIX.

Ignoring this kind of error is usually a bad idea, and it can even be
dangerous (e.g. by introducing a security hole). Developers should be
strongly encouraged to write code that handles the error. It’s common
for developers to want to handle errors from different operations in the
same basic way, either by reporting the error to the user or passing the
error back to their own clients.

These errors will be the focus of this proposal.

The final two classes of error are outside the scope of this proposal. A
universal error is theoretically recoverable, but by its nature the
language can’t help the programmer anticipate where it will come from.
A logic failure arises from a programmer mistake and should not be
recoverable at all. In our system, these kinds of errors are reported
either with Objective-C/C++ exceptions or simply by logging a message
and calling abort(). Both kinds of error are discussed extensively in
the rationale. Having considered them carefully, we believe that we can
address them in a later release without significant harm.

Aspects of the Design

This approach proposed here is very similar to the error handling model
manually implemented in Objective-C with the NSError convention.
Notably, the approach preserves these advantages of this convention:

  • Whether a method produces an error (or not) is an explicit part of
    its API contract.
  • Methods default to not producing errors unless they are explicitly
    marked.
  • The control flow within a function is still mostly explicit: a
    maintainer can tell exactly which statements can produce an error,
    and a simple inspection reveals how the function reacts to the
    error.
  • Throwing an error provides similar performance to allocating an
    error and returning it — it isn’t an expensive, table-based stack
    unwinding process.
  • Cocoa APIs using standard NSError patterns can be imported into
    this world automatically. Other common patterns (e.g. CFError,
    errno) can be added to the model in future versions of Swift.

In addition, we feel that this design improves on Objective-C’s error
handling approach in a number of ways:

  • It eliminates a lot of boilerplate control-flow code for propagating
    errors.
  • The syntax for error handling will feel familiar to people used to
    exception handling in other languages.
  • Defining custom error types is simple and ties in elegantly with
    Swift enums.

As to basic syntax, we decided to stick with the familiar language of
exception handling. We considered intentionally using different terms
(like raise / handle) to try to distinguish our approach from other
languages. However, by and large, error propagation in this proposal
works like it does in exception handling, and people are inevitably
going to make the connection. Given that, we couldn’t find a compelling
reason to deviate from the throw / catch legacy.

This document just contains the basic proposal and will be very light on
rationale. We considered many different languages and programming
environments as part of making this proposal, and there’s an extensive
discussion of them in the separate rationale document. For example, that
document explains why we don’t simply allow all functions to throw, why
we don’t propagate errors using simply an ErrorOr<T> return type, and
why we don’t just make error propagation part of a general monad
feature. We encourage you to read that rationale if you’re interested
in understanding why we made the decisions we did.

With that out of the way, let’s get to the details of the proposal.

Typed propagation

Whether a function can throw is part of its type. This applies to all
functions, whether they’re global functions, methods, or closures.

By default, a function cannot throw. The compiler statically enforces
this: anything the function does which can throw must appear in a
context which handles all errors.

A function can be declared to throw by writing throws on the function
declaration or type:

func foo() -> Int {          // This function is not permitted to throw.
func bar() throws -> Int {   // This function is permitted to throw.

throws is written before the arrow to give a sensible and consistent
grammar for function types and implicit () result types, e.g.:

func baz() throws {

// Takes a 'callback' function that can throw.
// 'fred' itself can also throw.
func fred(_ callback: (UInt8) throws -> ()) throws {

// These are distinct types.
let a : () -> () -> ()
let b : () throws -> () -> ()
let c : () -> () throws -> ()
let d : () throws -> () throws -> ()

For curried functions, throws only applies to the innermost function.
This function has type (Int) -> (Int) throws -> Int:

func jerry(_ i: Int)(j: Int) throws -> Int {

throws is tracked as part of the type system: a function value must
also declare whether it can throw. Functions that cannot throw are a
subtype of functions that can, so you can use a function that can’t
throw anywhere you could use a function that can:

func rachel() -> Int { return 12 }
func donna(_ generator: () throws -> Int) -> Int { ... }

donna(rachel)

The reverse is not true, since the caller would not be prepared to
handle the error.

A call to a function which can throw within a context that is not
allowed to throw is rejected by the compiler.

It isn’t possible to overload functions solely based on whether the
functions throw. That is, this is not legal:

func foo() {
func foo() throws {

A throwing method cannot override a non-throwing method or satisfy a
non-throwing protocol requirement. However, a non-throwing method can
override a throwing method or satisfy a throwing protocol requirement.

It is valuable to be able to overload higher-order functions based on
whether an argument function throws, so this is allowed:

func foo(_ callback: () throws -> Bool) {
func foo(_ callback: () -> Bool) {

rethrows

Functions which take a throwing function argument (including as an
autoclosure) can be marked as rethrows:

extension Array {
    func map<U>(_ fn: ElementType throws -> U) rethrows -> [U]
}

It is an error if a function declared rethrows does not include a
throwing function in at least one of its parameter clauses.

rethrows is identical to throws, except that the function promises
to only throw if one of its argument functions throws.

More formally, a function is rethrowing-only for a function f if:

  • it is a throwing function parameter of f,
  • it is a non-throwing function, or
  • it is implemented within f (i.e. it is either f or a function or
    closure defined therein) and it does not throw except by either:

    • calling a function that is rethrowing-only for f or
    • calling a function that is rethrows, passing only functions
      that are rethrowing-only for f.

It is an error if a rethrows function is not rethrowing-only for
itself.

A rethrows function is considered to be a throwing function. However,
a direct call to a rethrows function is considered to not throw if it
is fully applied and none of the function arguments can throw. For
example:

// This call to map is considered not to throw because its
// argument function does not throw.
let absolutePaths = paths.map { "/" + $0 }

// This call to map is considered to throw because its
// argument function does throw.
let streams = try absolutePaths.map { try InputStream(filename: $0) }

For now, rethrows is a property of declared functions, not of function
values. Binding a variable (even a constant) to a function loses the
information that the function was rethrows, and calls to it will use
the normal rules, meaning that they will be considered to throw
regardless of whether a non-throwing function is passed.

For the purposes of override and conformance checking, rethrows lies
between throws and non-throws. That is, an ordinary throwing method
cannot override a rethrows method, which cannot override a
non-throwing method; but an ordinary throwing method can be overridden
by a rethrows method, which can be overridden by a non-throwing
method. Equivalent rules apply for protocol conformance.

Throwing an error

The throw statement begins the propagation of an error. It always
takes an argument, which can be any value that conforms to the Error
protocol (described below).

if timeElapsed > timeThreshold {
    throw HomeworkError.Overworked
}

throw NSError(domain: "whatever", code: 42, userInfo: nil)

As mentioned above, attempting to throw an error out of a function not
marked throws is a static compiler error.

Catching errors

A catch clause includes an optional pattern that matches the error.
This pattern can use any of the standard pattern-matching tools provided
by switch statements in Swift, including boolean where conditions.
The pattern can be omitted; if so, a where condition is still
permitted. If the pattern is omitted, or if it does not bind a different
name to the error, the name error is automatically bound to the error
as if with a let pattern.

The try keyword is used for other purposes which it seems to fit far
better (see below), so catch clauses are instead attached to a
generalized do statement:

// Simple do statement (without a trailing while condition),
// just provides a scope for variables defined inside of it.
do {
    let x = foo()
}

// do statement with two catch clauses.
do {
    ...

} catch HomeworkError.Overworked {
    // a conditionally-executed catch clause

} catch _ {
    // a catch-all clause.
}

As with switch statements, Swift makes an effort to understand whether
catch clauses are exhaustive. If it can determine it is, then the
compiler considers the error to be handled. If not, the error
automatically propagates out of scope, either to a lexically enclosing
catch clause or out of the containing function (which must be marked
throws).

We expect to refine the catch syntax with usage experience.

Error

The Swift standard library will provide Error, a protocol with a very
small interface (which is not described in this proposal). The standard
pattern should be to define the conformance of an enum to the type:

enum HomeworkError : Error {
    case Overworked
    case Impossible
    case EatenByCat(Cat)
    case StopStressingMeWithYourRules
}

The enum provides a namespace of errors, a list of possible errors
within that namespace, and optional values to attach to each option.

Note that this corresponds very cleanly to the NSError model of an
error domain, an error code, and optional user data. We expect to import
system error domains as enums that follow this approach and implement
Error. NSError and CFError themselves will also conform to
Error.

The physical representation (still being nailed down) will make it
efficient to embed an NSError as an Error and vice-versa. It should
be possible to turn an arbitrary Swift enum that conforms to Error
into an NSError by using the qualified type name as the domain key,
the enumerator as the error code, and turning the payload into user
data.

Automatic, marked, propagation of errors

Once an error is thrown, Swift will automatically propagate it out of
scopes (that permit it), rather than relying on the programmer to
manually check for errors and do their own control flow. This is just a
lot less boilerplate for common error handling tasks. However, doing
this naively would introduce a lot of implicit control flow, which makes
it difficult to reason about the function’s behavior. This is a serious
maintenance problem and has traditionally been a considerable source of
bugs in languages that heavily use exceptions.

Therefore, while Swift automatically propagates errors, it requires that
statements and expressions that can implicitly throw be marked with the
try keyword. For example:

func readStuff() throws {
    // loadFile can throw an error.  If so, it propagates out of readStuff.
    try loadFile("mystuff.txt")

    // This is a semantic error; the 'try' keyword is required
    // to indicate that it can throw.
    var y = stream.readFloat()

    // This is okay; the try covers the entire statement.
    try y += stream.readFloat()

    // This try applies to readBool().
    if try stream.readBool() {
    // This try applies to both of these calls.
    let x = try stream.readInt() + stream.readInt()
    }

    if let err = stream.getOutOfBandError() {
    // Of course, the programmer doesn't have to mark explicit throws.
    throw err
    }
}

Developers can choose to «scope» the try very tightly by writing it
within parentheses or on a specific argument or list element:

// Ok.
let x = (try stream.readInt()) + (try stream.readInt())

// Semantic error: the try only covers the parenthesized expression.
let x2 = (try stream.readInt()) + stream.readInt()

// The try applies to the first array element.  Of course, the
// developer could cover the entire array by writing the try outside.
let array = [ try foo(), bar(), baz() ]

Some developers may wish to do this to make the specific throwing calls
very clear. Other developers may be content with knowing that something
within a statement can throw. The compiler’s fixit hints will guide
developers towards inserting a single try that covers the entire
statement. This could potentially be controlled someday by a coding
style flag passed to the compiler.

try!

To concisely indicate that a call is known to not actually throw at
runtime, try can be decorated with !, turning the error check into a
runtime assertion that the call does not throw.

For the purposes of checking that all errors are handled, a try!
expression is considered to handle any error originating from within its
operand.

try! is otherwise exactly like try: it can appear in exactly the
same positions and doesn’t affect the type of an expression.

Manual propagation and manipulation of errors

Taking control over the propagation of errors is important for some
advanced use cases (e.g. transporting an error result across threads
when synchronizing a future) and can be more convenient or natural for
specific use cases (e.g. handling a specific call differently within a
context that otherwise allows propagation).

As such, the Swift standard library should provide a standard Rust-like
Result<T> enum, along with API for working with it, e.g.:

  • A function to evaluate an error-producing closure and capture the
    result as a Result<T>.
  • A function to unpack a Result<T> by either returning its value or
    propagating the error in the current context.

This is something that composes on top of the basic model, but that has
not been designed yet and details aren’t included in this proposal.

The name Result<T> is a stand-in and needs to be designed and
reviewed, as well as the basic operations on the type.

defer

Swift should provide a defer statement that sets up an ad hoc
clean-up action to be run when the current scope is exited. This
replicates the functionality of a Java-style finally, but more cleanly
and with less nesting.

This is an important tool for ensuring that explicitly-managed resources
are released on all paths. Examples include closing a network connection
and freeing memory that was manually allocated. It is convenient for all
kinds of error-handling, even manual propagation and simple domain
errors, but is especially nice with automatic propagation. It is also a
crucial part of our long-term vision for universal errors.

defer may be followed by an arbitrary statement. The compiler should
reject a defer action that might terminate early, whether by throwing
or with return, break, or continue.

Example:

if exists(filename) {
    let file = open(filename, O_READ)
    defer close(file)

    while let line = try file.readline() {
    ...
    }

    // close occurs here, at the end of the formal scope.
}

If there are multiple defer statements in a scope, they are guaranteed
to be executed in reverse order of appearance. That is:

let file1 = open("hello.txt")
defer close(file1)
let file2 = open("world.txt")
defer close(file2)
...
// file2 will be closed first.

A potential extension is to provide a convenient way to mark that a
defer action should only be taken if an error is thrown. This is a
convenient shorthand for controlling the action with a flag. We will
evaluate whether adding complexity to handle this case is justified
based on real-world usage experience.

Importing Cocoa

If possible, Swift’s error-handling model should transparently work
with the SDK with a minimal amount of effort from framework owners.

We believe that we can cover the vast majority of Objective-C APIs with
NSError** out-parameters by importing them as throws and removing
the error clause from their signature. That is, a method like this one
from NSAttributedString:

- (NSData *)dataFromRange:(NSRange)range
       documentAttributes:(NSDictionary *)dict
                    error:(NSError **)error;

would be imported as:

func dataFromRange(
    _ range: NSRange,
    documentAttributes dict: NSDictionary
) throws -> NSData

There are a number of cases to consider, but we expect that most can be
automatically imported without extra annotation in the SDK, by using a
couple of simple heuristics:

  • The most common pattern is a BOOL result, where a false value
    means an error occurred. This seems unambiguous.

  • Also common is a pointer result, where a nil result usually means
    an error occurred. This appears to be universal in Objective-C; APIs
    that can return nil results seem to do so via out-parameters. So
    it seems to be safe to make a policy decision that it’s okay to
    assume that a nil result is an error by default.

    If the pattern for a method is that a nil result means it produced
    an error, then the result can be imported as a non-optional type.

  • A few APIs return void. As far as I can tell, for all of these,
    the caller is expected to check for a non-nil error.

For other sentinel cases, we can consider adding a new clang attribute
to indicate to the compiler what the sentinel is:

  • There are several APIs returning NSInteger or NSUInteger. At
    least some of these return 0 on error, but that doesn’t seem like a
    reasonable general assumption.
  • AVFoundation provides a couple methods returning
    AVKeyValueStatus. These produce an error if the API returned
    AVKeyValueStatusFailed, which, interestingly enough, is not the
    zero value.

The clang attribute would specify how to test the return value for an
error. For example:

+ (NSInteger)writePropertyList:(id)plist
                      toStream:(NSOutputStream *)stream
                        format:(NSPropertyListFormat)format
                       options:(NSPropertyListWriteOptions)opt
                         error:(out NSError **)error
    NS_ERROR_RESULT(0);

- (AVKeyValueStatus)statusOfValueForKey:(NSString *)key
                                  error:(NSError **)
    NS_ERROR_RESULT(AVKeyValueStatusFailed);

We should also provide a Clang attribute which specifies that the
correct way to test for an error is to check the out-parameter. Both of
these attributes could potentially be used by the static analyzer, not
just Swift. (For example, they could try to detect an invalid error
check.)

Cases that do not match the automatically imported patterns and that
lack an attribute would be left unmodified (i.e., they’d keep their
NSErrorPointer argument) and considered «not awesome» in the SDK
auditing tool. These will still be usable in Swift: callers will get the
NSError back like they do today, and have to throw the result manually.

For initializers, importing an initializer as throwing takes precedence
over importing it as failable. That is, an imported initializer with a
nullable result and an error parameter would be imported as throwing.
Throwing initializers have very similar constraints to failable
initializers; in a way, it’s just a new axis of failability.

One limitation of this approach is that we need to be able to
reconstruct the selector to use when an overload of a method is
introduced. For this reason, the import is likely to be limited to
methods where the error parameter is the last one and the corresponding
selector chunk is either error: or the first chunk (see below).
Empirically, this seems to do the right thing for all but two sets of
APIs in the public API:

  • The ISyncSessionDriverDelegate category on NSObject declares
    half-a-dozen methods like this:

    - (BOOL)sessionDriver:(ISyncSessionDriver *)sender
            didRegisterClientAndReturnError:(NSError **)outError;

    Fortunately, these delegate methods were all deprecated in Lion, and
    are thus unavailable in Swift.

  • NSFileCoordinator has half a dozen methods where the error:
    clause is second-to-last, followed by a block argument. These
    methods are not deprecated as far as I know.

The above translation rule would import methods like this one from
NSDocument:

- (NSDocument *)duplicateAndReturnError:(NSError **)outError;

like so:

func duplicateAndReturnError() throws -> NSDocument

The AndReturnError bit is common but far from universal; consider this
method from NSManagedObject:

- (BOOL)validateForDelete:(NSError **)error;

This would be imported as:

func validateForDelete() throws

This is a really nice import, and it’s somewhat unfortunate that we
can’t import duplicateAndReturnError: as duplicate().

Potential future extensions to this model

We believe that the proposal above is sufficient to provide a huge step
forward in error handling in Swift programs, but there is always more to
consider in the future. Some specific things we’ve discussed (and may
come back to in the future) but don’t consider to be core to the Swift
2.0 model are:

Higher-order polymorphism

We should make it easy to write higher-order functions that behave
polymorphically with respect to whether their arguments throw. This can
be done in a fairly simple way: a function can declare that it throws if
any of a set of named arguments do. As an example (using strawman
syntax):

func map<T, U>(_ array: [T], fn: T -> U) throwsIf(fn) -> [U] {
    ...
}

There’s no need for a more complex logical operator than disjunction
for normal higher-order stuff.

This feature is highly desired (e.g. it would allow many otherwise
redundant overloads to be collapsed into a single definition), but it
may or may not make it into Swift 2.0 based on schedule limitations.

Generic polymorphism

For similar reasons to higher-order polymorphism, we should consider
making it easier to parameterize protocols on whether their operations
can throw. This would allow the writing of generic algorithms, e.g. over
Sequence, that handle both conformances that cannot throw (like
Array) and those that can (like a hypothetical cloud-backed
implementation).

However, this would be a very complex feature, yet to be designed, and
it is far out-of-scope for Swift 2.0. In the meantime, most standard
protocols will be written to not allow throwing conformances, so as to
not burden the use of common generic algorithms with spurious
error-handling code.

Statement-like functions

Some functions are designed to take trailing closures that feel like
sub-statements. For example, autoreleasepool can be used this way:

autoreleasepool {
    foo()
}

The error-handling model doesn’t cause major problems for this. The
compiler can infer that the closure throws, and autoreleasepool can be
overloaded on whether its argument closure throws; the overload that
takes a throwing closures would itself throw.

There is one minor usability problem here, though. If the closure
contains throwing expressions, those expressions must be explicitly
marked within the closure with try. However, from the compiler’s
perspective, the call to autoreleasepool is also a call that can
throw, and so it must also be marked with try:

try autoreleasepool {              // 'try' is required here...
    let string = try parseString() // ...and here.
    ...
}

This marking feels redundant. We want functions like autoreleasepool
to feel like statements, but marks inside built-in statements like if
don’t require the outer statement to be marked. It would be better if
the compiler didn’t require the outer try.

On the other hand, the «statement-like» story already has a number of
other holes: for example, break, continue, and return behave
differently in the argument closure than in statements. In the future,
we may consider fixing that; that fix will also need to address the
error-propagation problem.

using

A using statement would acquire a resource, holds it for a fixed
period of time, optionally binds it to a name, and then releases it
whenever the controlled statement exits. using has many similarities
to defer. It does not subsume defer, which is useful for many ad-hoc
and tokenless clean-ups. But it could be convenient for the common
pattern of a type-directed clean-up.

Automatically importing CoreFoundation and C functions

CF APIs use CFErrorRef pretty reliably, but there are several problems
here: 1) the memory management rules for CFErrors are unclear and
potentially inconsistent. 2) we need to know when an error is raised.

In principle, we could import POSIX functions into Swift as throwing
functions, filling in the error from errno. It’s nearly impossible to
imagine doing this with an automatic import rule, however; much more
likely, we’d need to wrap them all in an overlay.

In both cases, it is possible to pull these into the Swift error
handling model, but because this is likely to require massive SDK
annotations it is considered out of scope for iOS 9/OS X 10.11 & Swift
2.0.

Unexpected and universal errors

As discussed above, we believe that we can extend our current model to
support untyped propagation for universal errors. Doing this well, and
in particular doing it without completely sacrificing code size and
performance, will take a significant amount of planning and insight. For
this reason, it is considered well out of scope for Swift 2.0.

Мы используем обработку ошибок с помощью do-try-catch для реагирования на исправимые ошибки. Это дает нам больший контроль над различными ошибочными сценариями, которые могут возникнуть в нашем коде, например, при вводе неправильного имени пользователя или пароля.

Зачем нужно отслеживать ошибки?

В приложении некоторые ошибки могут быть результатом ошибок программиста. Когда ваше приложение вылетает с сообщением «Index out of bounds», вы, вероятно, где-то допустили ошибку. И точно так же, когда вы принудительно извлекаете опциональное значение, которое имеет значение nil, ваше приложение падает.

В практической разработке iOS некоторые ошибки являются частью работы приложения, например, сообщение «Недостаточно средств» при попытке оплаты с помощью карты.

Ошибки такого рода исправимы. Их можно обработать и отреагировать соответствующим образом. К примеру:

  • При попытке снять деньги в банкомате отображается «Неверный PIN-код».
  • Ваш автомобиль показывает индикатор низкого уровня топлива при попытке запустить двигатель.
  • Попытка аутентификации для API возвращает «Неверное имя пользователя / пароль».

Вы можете работать с этими ошибками, отобразив сообщение с предупреждением или сделав что-то еще. Например, ваша карта блокируется после 3 неудачных попыток. Ваш автомобиль может указать вам ближайшую заправку, когда у вас кончается бензин. Вы можете попробовать ввести другое имя пользователя и пароль.

Swift поддерживает обработку ошибок с помощью блока кода do-try-catch.

Выбрасывание ошибок

Когда в вашем коде возникает сценарий, который может привести к ошибке, вы можете выбросить ошибку:

if fuel < 1000 {
    throw RocketError.insufficientFuel
}

В приведенном выше коде ключевое слово throw используется для выдачи ошибки типа RocketError.insufficientFuel, когда переменная fuel меньше, чем 1000.

Представьте, что мы пытаемся запустить ракету:

func igniteRockets(fuel: Int, astronauts: Int) throws {
    if fuel < 1000 {
        throw RocketError.insufficientFuel
    }
    else if astronauts < 3 {
        throw RocketError.insufficientAstronauts(needed: 3)
    }
 
    // Запуск ракеты
    print("3... 2... 1... Старт!")
}

Функция igniteRockets(fuel:astronauts:) будет запускать ракеты, только если значение fuel больше или равно 1000 и если на борту есть как минимум 3 астронавта.

Функция igniteRockets(…) также помечается ключевым словом throws. Это ключевое слово указывает, что ошибки должны быть обработаны.

В приведенном выше коде мы используем тип ошибки RocketError:

enum RocketError: Error {
    case insufficientFuel
    case insufficientAstronauts(needed: Int)
    case unknownError
}

Данное перечисление определяет три типа ошибок: .insufficientFuel, insufficientAstronauts(needed) и .unknownError. Определение ваших собственных типов ошибок полезно, потому что это поможет четко понять, что эти ошибки означают в вашем коде.

Возьмем, например, ошибку insufficientAstronauts(needed:). Когда выдается эта ошибка, вы можете использовать аргумент needed:, который указывает, сколько астронавтов необходимо для успешного запуска ракеты.

Ключевое слово throw имеет тот же эффект, что и ключевое слово return. Когда выполняется throw, выполнение функции останавливается, и выброшенная ошибка передается вызывающей функции.

Теперь мы можем использовать обработку ошибок, чтобы соответствующим образом реагировать на сценарии ошибок. Обработка ошибок в Swift осуществляется с помощью блока кода do-try-catch:

do {
    try igniteRockets(fuel: 5000, astronauts: 1)    
} catch {
    print(error)
}

Обработка ошибок имеет три аспекта:

  • К функции, которая может вызвать ошибку, добавляется ключевое слово try.
  • Блок кода, который включает ключевое слово try, обернут в do { … }.
  • Один или несколько блоков catch { … } могут быть присоединены к do { … } для обработки отдельных случаев ошибок.

Если функция выдает ошибку, вызывается блок catch. В данном случае это выводит ошибку на консоль.

Вы также можете реагировать на ошибки в индивидуальном порядке:

do {
    try igniteRockets(fuel: 5000, astronauts: 1)    
} catch RocketError.insufficientFuel {
    print("Ракете нужно больше топлива!")
} catch RocketError.insufficientAstronauts(let needed) {
    print("Нужно как минимум (needed) астронавта...")
}

Вышеуказанные блоки catch вызываются на основании отдельных перечислений RocketError. Вы можете напрямую получить доступ к связанным значениям перечислений, таких как needed. Также вы можете использовать выражения с шаблоном where чтобы получить больший контроль над ошибочным сценарием.

enum RocketError: Error {
    case insufficientFuel
    case insufficientAstronauts(needed: Int)
    case unknownError
}
 
func igniteRockets(fuel: Int, astronauts: Int) throws {
    if fuel < 1000 {
        throw RocketError.insufficientFuel
    }
    else if astronauts < 3 {
        throw RocketError.insufficientAstronauts(needed: 3)
    }
 
    // Ignite rockets
    print("3... 2... 1... Полет!")
}
 
do {
    try igniteRockets(fuel: 5000, astronauts: 1)
} catch {
    print(error)
}

Преобразование ошибок в опционалы с помощью try?

Целью обработки ошибок является явное определение того, что происходит при возникновении ошибки. Это позволяет нам реагировать определенным образом на ошибки.

В некоторых случаях нас не волнует сама ошибка. Нам просто нужно получить значение из функции. И если возникает ошибка, мы можем возвратить nil. Эта возможность доступна с помощью ключевого слова try? Когда вы используете try?, вам не нужно использовать полный блок кода do-try-catch.

let result = try? calculateValue(for: 42)

Представьте, что функция может выбрасывать ошибки, если ее параметр недействителен. Вместо обработки ошибки мы конвертируем возвращаемое значение в опциональное.

Возможны два сценария:

  • Функция не выдает ошибку и возвращает значение, которое присваивается константе result.
  • Функция выдает ошибку и не возвращает значение. Это означает, что константе result присваивается nil.

Обработка ошибок с помощью try? означает, что вы можете воспользоваться синтаксисом, специфичным для опционалов, таких как объединение по nil и опциональное связывание:

if let result = try? calculateValue(for: 99) {
    // 
}
 
let result = try? calculateValue(for: 123) ?? 101

Отключение обработки ошибок с помощью try!

Вы можете полностью отключить обработку ошибок с помощью try!. Ключевое слово try! используется для принудиального извлечения опционального значения.

В отличие от того try?, который возвращает опциональное значение, синтаксис try! приведет к сбою вашего кода в случае возникновения ошибки. Есть два различных сценария, в которых использование try! может быть полезно:

  • Используйте try!, когда вы на 100% уверенны, что ошибка не возникнет.
  • Используйте, try!, когда невозможно продолжить выполнение кода.

Представьте, что вы пишите приложение, в которое встроен файл базы данных. Функция загрузки базы данных выдает ошибку, когда база данных повреждена. Вы можете использовать try! для загрузки базы данных в память, потому что, если база данных повреждена, приложение все равно не сможет быть использовано.

Время на прочтение
5 мин

Количество просмотров 10K

Сегодня мы приготовили перевод для тех, кто так же, как автор статьи, при изучении Документации языка программирования Swift избегает главы «Error Handling».

Из статьи вы узнаете:

  • что такое оператор if-else и что с ним не так;
  • как подружиться с Error Handling;
  • когда стоит использовать Try! и Try?

Моя история

Когда я был младше, я начинал изучать документацию языка Swift. Я по несколько раз прочёл все главы, кроме одной: «Error Handling». Отчего-то мне казалось, что нужно быть профессиональным программистом, чтобы понять эту главу.

Я боялся обработки ошибок. Такие слова, как catch, try, throw и throws, казались бессмысленными. Они просто пугали. Неужели они не выглядят устрашающими для человека, который видит их в первый раз? Но не волнуйтесь, друзья мои. Я здесь, чтобы помочь вам.

Как я объяснил своей тринадцатилетней сестре, обработка ошибок – это всего лишь ещё один способ написать блок if-else для отправки сообщения об ошибке.

Сообщение об ошибке от Tesla Motors

Как вы наверняка знаете, у автомобилей Tesla есть функция автопилота. Но, если в работе машины по какой-либо причине происходит сбой, она просит вас взять руль в руки и сообщает об ошибке. В этом уроке мы узнаем, как выводить такое сообщение с помощью Error Handling.

Мы создадим программу, которая будет распознавать такие объекты, как светофоры на улицах. Для этого нужно знать как минимум машинное обучение, векторное исчисление, линейную алгебру, теорию вероятности и дискретную математику. Шутка.

Знакомство с оператором if-else

Чтобы максимально оценить Error Handling в Swift, давайте оглянемся в прошлое. Вот что многие, если не все, начинающие разработчики сделали бы, столкнувшись с сообщением об ошибке:

var isInControl = true

func selfDrive() {
 if isInControl {
  print("You good, let me ride this car for ya")
 } else {
  print("Hold the handlebar RIGHT NOW, or you gone die")
 }
}

selfDrive() // "You good..."

Проблема

Самая большая проблема заключается в удобочитаемости кода, когда блок else становится слишком громоздким. Во-первых, вы не поймёте, содержит ли сама функция сообщение об ошибке, до тех пор, пока не прочитаете функцию от начала до конца или если не назовёте ее, например, selfDriveCanCauseError, что тоже сработает.

Смотрите, функция может убить водителя. Необходимо в недвусмысленных выражениях предупредить свою команду о том, что эта функция опасна и даже может быть смертельной, если невнимательно с ней обращаться.

С другой проблемой можно столкнуться при выполнении некоторых сложных функций или действий внутри блока else. Например:

else {
 print("Hold the handle bar Right now...")

 // If handle not held within 5 seconds, car will shut down 
 // Slow down the car
 // More code ...
 // More code ...

}

Блок else раздувается, и работать с ним – все равно что пытаться играть в баскетбол в зимней одежде (по правде говоря, я так и делаю, так как в Корее достаточно холодно). Вы понимаете, о чём я? Это некрасиво и нечитабельно.

Поэтому вы просто могли бы добавить функцию в блок else вместо прямых вызовов.


else { 
 slowDownTheCar()
 shutDownTheEngine()
}

Однако при этом сохраняется первая из выделенных мной проблем, плюс нет какого-то определённого способа обозначить, что функция selfDrive() опасна и что с ней нужно обращаться с осторожностью. Поэтому предлагаю погрузиться в Error Handling, чтобы писать модульные и точные сообщения об ошибках.

Знакомство с Error Handling

К настоящему времени вы уже знаете о проблеме If-else с сообщениями об ошибках. Пример выше был слишком простым. Давайте предположим, что есть два сообщения об ошибке:

  1. вы заблудились
  2. аккумулятор автомобиля разряжается.

Я собираюсь создать enum, который соответствует протоколу Error.

enum TeslaError: Error {
 case lostGPS
 case lowBattery 
}

Честно говоря, я точно не знаю, что делает Error протокол, но при обработке ошибок без этого не обойдешься. Это как: «Почему ноутбук включается, когда нажимаешь на кнопку? Почему экран телефона можно разблокировать, проведя по нему пальцем?»

Разработчики Swift так решили, и я не хочу задаваться вопросом об их мотивах. Я просто использую то, что они для нас сделали. Конечно, если вы хотите разобраться подробнее, вы можете загрузить программный код Swift и проанализировать его самостоятельно – то есть, по нашей аналогии, разобрать ноутбук или iPhone. Я же просто пропущу этот шаг.

Если вы запутались, потерпите еще несколько абзацев. Вы увидите, как все станет ясно, когда TeslaError превратится в функцию.

Давайте сперва отправим сообщение об ошибке без использования Error Handling.

var lostGPS: Bool = true
var lowBattery: Bool = false

func autoDriveTesla() {
 if lostGPS {
  print("I'm lost, bruh. Hold me tight")
  // A lot more code

 }
 if lowBattery {
  print("HURRY! ")
  // Loads of code 
 }
}

Итак, если бы я запустил это:


autoDriveTesla() // "HURRY! " 

Но давайте используем Error Handling. В первую очередь вы должны явно указать, что функция опасна и может выдавать ошибки. Мы добавим к функции ключевое слово throws.


func autoDriveTesla() throws { ... }

Теперь функция автоматически говорит вашим товарищам по команде, что autoDriveTesla – особый случай, и им не нужно читать весь блок.

Звучит неплохо? Отлично, теперь пришло время выдавать эти ошибки, когда водитель сталкивается с lostGPA или lowBattery внутри блока Else-If. Помните про enum TeslaError?

func autoDriveTesla() throws {
 if lostGPS {
  throw TeslaError.lostGPS

}
 if lowBattery {
  throw TeslaError.lowBattery
}

Я вас всех поймаю

Если lostGPS равно true, то функция отправит TeslaError.lostGPS. Но что делать потом? Куда мы будем вставлять это сообщение об ошибке и добавлять код для блока else?

print("Bruh, I'm lost. Hold me tight")

Окей, я не хочу заваливать вас информацией, поэтому давайте начнём с того, как выполнить функцию, когда в ней есть ключевое слово throws.

Так как это особый случай, вам необходимо добавлять try внутрь блока do при работе с этой функцией. Вы такие: «Что?». Просто последите за ходом моих мыслей ещё чуть-чуть.

do {
 try autoDriveTesla() 
}

Я знаю, что вы сейчас думаете: «Я очень хочу вывести на экран моё сообщение об ошибке, иначе водитель умрёт».

Итак, куда мы вставим это сообщение об ошибке? Мы знаем, что функция способна отправлять 2 возможных сообщения об ошибке:

  1. TeslaError.lowBattery
  2. TeslaError.lostGPS.

Когда функция выдаёт ошибку, вам необходимо её “поймать” и, как только вы это сделаете, вывести на экран соответствующее сообщение. Звучит немного запутанно, поэтому давайте посмотрим.

var lostGPS: Bool = false
var lowBattery: Bool = true

do {
 try autoDriveTesla() 
 } catch TeslaError.lostGPS {
  print("Bruh, I'm lost. Hold me tight")
 } catch TeslaError.lowBattery {
  print("HURRY! ")
 }
}

// Results: "HURRY! "

Теперь всё должно стать понятно. Если понятно не всё, вы всегда можете посмотреть моё видео на YouTube.

Обработка ошибок с Init

Обработка ошибок может применяться не только к функциям, но и тогда, когда вам нужно инициализировать объект. Допустим, если вы не задали имя курса, то нужно выдавать ошибку.

Если вы введёте tryUdemyCourse(name: «»), появится сообщение об ошибке.

Когда использовать Try! и Try?

Хорошо. Try используется только тогда, когда вы выполняете функцию/инициализацию внутри блока do-catch. Однако если у вас нет цели предупредить пользователя о том, что происходит, выводя сообщение об ошибке на экран, или как-то исправить ее, вам не нужен блок catch.

try?– что это?

Давайте начнём с try? Хотя это не рекомендуется,

let newCourse = try? UdemyCourse("Functional Programming")

try? всегда возвращает опциональный объект, поэтому необходимо извлечь newCourse

if let newCourse = newCourse { ... }

Если метод init выбрасывает ошибку, как, например

let myCourse = try? UdemyCourse("") // throw NameError.noName

то myCourse будет равен nil.

try! – что это?

В отличие от try? оно возвращает не опциональное значение, а обычное. Например,

let bobCourse = try! UdemyCourse("Practical POP")

bobCourse не опционально. Однако, если при методе инициализации выдается ошибка вроде,

let noCourseName = try! UdemyCourse("") // throw NameError.noName

то приложение упадёт. Так же как и в случае с принудительным извлечением с помощью !, никогда не используйте его, если вы не уверены на 101% в том, что происходит.

Ну вот и всё. Теперь вы вместе со мной поняли концепцию Error Handling. Легко и просто! И не нужно становиться профессиональным программистом.

title description ms.custom ms.date ms.prod ms.reviewer ms.suite ms.tgt_pltfrm ms.topic ms.assetid caps.latest.revision author ms.author manager

SWIFT error codes in BizTalk Server | Microsoft Docs

View the class and validation types for the SWIFT Accelerator in BizTalk Server

08/16/2017

biztalk-server

article

03699986-965b-4a28-ab2e-09f110fb4db6

4

MandiOhlinger

mandia

anneta

SWIFT defines many network-imposed validations against the set of financial (FIN) messages. Each validation relates to a type of check against the contents of the message, and is associated with a three-character error code. The first character of the error code implies the class of the problem detected, and is a letter. The remaining two characters denote the detail of the error (when combined with the class) and always appear as a two-digit code.

Class of errors

The following table lists the letter designations, validation type, rule change associated with each class of error, and whether or not the class of error is supported.

Class Validation type and rule change Supported?
C, D, E Semantic validation rules 0-299 Supported
Knn Invalid code word in field nn Supported
M50 Message length exceeded Unsupported
M60 Non-SWIFT character encountered Supported
T Text validation error codes Supported
G Specific error codes for message user group (MUG) Textval rules Unsupported
B Special error codes for value-added services Unsupported

All SWIFT errors should be referenced in the SWIFT User Handbook. For more information and for a complete list of SWIFT error codes, refer to the Message Format Validation Rules volume of the SWIFT User Handbook. [!INCLUDEbtaA4SWIFT2.3abbrevnonumber] implements the rules in the September 2003 edition of this publication. You can access the SWIFT Web site at https://go.microsoft.com/fwlink/?LinkId=27885.

Validation errors

There are some codes which are defined by A4SWIFT. These error codes are used in the validation/network rules created and implemented by A4SWIFT, so there is no corresponding error code defined by SWIFT for such rules. Below table shows the error code and corresponding case in which the error is thrown. is the particular field which throws the error.

Error Code Description
A4SWIFT001 The first character of multiline field cannot be ‘:’ or ‘-‘ character for second and subsequent lines.
A4SWIFT002 Field contains invalid value.

[!NOTE]
[!INCLUDEA4SWIFT_CurrentVersion_FirstRef] includes support for some legacy messages, because internal applications might use these messages. Therefore, A4SWIFT maintains the associated SWIFT rules and error codes.

More good info

Troubleshooting: Issues and Resolutions
Known Issues
Common terms and definitions

title description ms.custom ms.date ms.prod ms.reviewer ms.suite ms.tgt_pltfrm ms.topic ms.assetid caps.latest.revision author ms.author manager

SWIFT error codes in BizTalk Server | Microsoft Docs

View the class and validation types for the SWIFT Accelerator in BizTalk Server

08/16/2017

biztalk-server

article

03699986-965b-4a28-ab2e-09f110fb4db6

4

MandiOhlinger

mandia

anneta

SWIFT defines many network-imposed validations against the set of financial (FIN) messages. Each validation relates to a type of check against the contents of the message, and is associated with a three-character error code. The first character of the error code implies the class of the problem detected, and is a letter. The remaining two characters denote the detail of the error (when combined with the class) and always appear as a two-digit code.

Class of errors

The following table lists the letter designations, validation type, rule change associated with each class of error, and whether or not the class of error is supported.

Class Validation type and rule change Supported?
C, D, E Semantic validation rules 0-299 Supported
Knn Invalid code word in field nn Supported
M50 Message length exceeded Unsupported
M60 Non-SWIFT character encountered Supported
T Text validation error codes Supported
G Specific error codes for message user group (MUG) Textval rules Unsupported
B Special error codes for value-added services Unsupported

All SWIFT errors should be referenced in the SWIFT User Handbook. For more information and for a complete list of SWIFT error codes, refer to the Message Format Validation Rules volume of the SWIFT User Handbook. [!INCLUDEbtaA4SWIFT2.3abbrevnonumber] implements the rules in the September 2003 edition of this publication. You can access the SWIFT Web site at https://go.microsoft.com/fwlink/?LinkId=27885.

Validation errors

There are some codes which are defined by A4SWIFT. These error codes are used in the validation/network rules created and implemented by A4SWIFT, so there is no corresponding error code defined by SWIFT for such rules. Below table shows the error code and corresponding case in which the error is thrown. is the particular field which throws the error.

Error Code Description
A4SWIFT001 The first character of multiline field cannot be ‘:’ or ‘-‘ character for second and subsequent lines.
A4SWIFT002 Field contains invalid value.

[!NOTE]
[!INCLUDEA4SWIFT_CurrentVersion_FirstRef] includes support for some legacy messages, because internal applications might use these messages. Therefore, A4SWIFT maintains the associated SWIFT rules and error codes.

More good info

Troubleshooting: Issues and Resolutions
Known Issues
Common terms and definitions

Обработка ошибок

Обработка ошибок — это процесс реагирования на возникновение ошибок и восстановление после появления ошибок в программе. Swift предоставляет первоклассную поддержку при генерации, вылавливании и переносе ошибок, устранении ошибок во время выполнения программы.

Некоторые операции не всегда гарантируют полное выполнение или конечный результат. Опционалы используются для обозначения отсутствия значения, но когда случается сбой, важно понять, что вызвало сбой, для того, чтобы соответствующим образом изменить код.

В качестве примера, рассмотрим задачу считывания и обработки данных из файла на диске. Задача может провалиться по нескольким причинам, в том числе: файл не существует по указанному пути, или файл не имеет разрешение на чтение, или файл не закодирован в необходимом формате. Отличительные особенности этих различных ситуаций позволяют программе решать некоторые ошибки самостоятельно и сообщать пользователю какие ошибки она не может решить сама.

Отображение и генерация ошибок

В Swift ошибки отображаются значениями типов, которые соответствуют протоколу Error. Этот пустой протокол является индикатором того, что это перечисление может быть использовано для обработки ошибок.

Перечисления в Swift особенно хорошо подходят для группировки схожих между собой условий возникновения ошибок и соответствующих им значений, что позволяет получить дополнительную информацию о природе самой ошибки. Например, вот как отображаются условия ошибки работы торгового автомата внутри игры:

enum VendingMachineError: Error {
    case invalidSelection
    case insufficientFunds(coinsNeeded: Int)
    case outOfStock
}

Генерация ошибки позволяет указать, что произошло что-то неожиданное и обычное выполнение программы не может продолжаться. Для того чтобы «сгенерировать» ошибку, вы используете инструкцию throw. Например, следующий код генерирует ошибку, указывая, что пять дополнительных монет нужны торговому автомату:

throw VendingMachineError.insufficientFunds(coinsNeeded: 5)

Обработка ошибок

Когда генерируется ошибка, то фрагмент кода, окружающий ошибку, должен быть ответственным за ее обработку: например, он должен исправить ее, или испробовать альтернативный подход, или просто информировать пользователя о неудачном исполнении кода.

В Swift существует четыре способа обработки ошибок. Вы можете передать (propagate) ошибку из функции в код, который вызывает саму эту функцию, обработать ошибку, используя инструкцию do-catch, обработать ошибку, как значение опционала, или можно поставить утверждение, что ошибка в данном случае исключена. Каждый вариант будет рассмотрен далее.

Когда функция генерирует ошибку, последовательность выполнения вашей программы меняется, поэтому важно сразу обнаружить место в коде, которое может генерировать ошибки. Для того, чтобы выяснить где именно это происходит, напишите ключевое слово try — или варианты try? или try!— до куска кода, вызывающего функцию, метод или инициализатор, который может генерировать ошибку. Эти ключевые слова описываются в следующем параграфе.

Заметка

Обработка ошибок в Swift напоминает обработку исключений (exceptions) в других языках, с использованием ключевых слов try, catch и throw. В отличие от обработки исключений во многих языках, в том числе и в Objective-C- обработка ошибок в Swift не включает разворачивание стека вызовов, то есть процесса, который может быть дорогим в вычислительном отношении. Таким образом, производительные характеристики инструкции throw сопоставимы с характеристиками оператора return.

Передача ошибки с помощью генерирующей функции

Чтобы указать, что функция, метод или инициализатор могут генерировать ошибку, вам нужно написать ключевое слово throws в реализации функции после ее параметров. Функция, отмеченная throws называется генерирующей функцией. Если у функции установлен возвращаемый тип, то вы пишете ключевое слово throws перед стрелкой возврата (->).

func canThrowErrors() throws -> String

func cannotThrowErrors() -> String

Генерирующая функция передает ошибки, которые возникают внутри нее в область вызова этой функции.

Заметка

Только генерирующая ошибку функция может передавать ошибки. Любые ошибки, сгенерированные внутри non-throwing функции, должны быть обработаны внутри самой функции.

В приведенном ниже примере VendingMachine класс имеет vend(itemNamed: ) метод, который генерирует соответствующую VendingMachineError, если запрошенный элемент недоступен, его нет в наличии, или имеет стоимость, превышающую текущий депозит:

struct Item {
    var price: Int
    var count: Int
}
 
class VendingMachine {
    var inventory = [
        "Candy Bar": Item(price: 12, count: 7),
        "Chips": Item(price: 10, count: 4),
        "Pretzels": Item(price: 7, count: 11)
    ]
    var coinsDeposited = 0
    
    func vend(itemNamed name: String) throws {
        guard let item = inventory[name] else {
            throw VendingMachineError.invalidSelection
        }
        
        guard item.count > 0 else {
            throw VendingMachineError.outOfStock
        }
        
        guard item.price <= coinsDeposited else {
            throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
        }
        
        coinsDeposited -= item.price
        
        var newItem = item
        newItem.count -= 1
        inventory[name] = newItem
        
        print("Dispensing (name)")
    }
}

Реализация vend(itemNamed: ) метода использует оператор guard для раннего выхода из метода и генерации соответствующих ошибок, если какое-либо требование для приобретения закуски не будет выполнено. Потому что инструкция throw мгновенно изменяет управление программой, и выбранная позиция будет куплена, только если все эти требования будут выполнены.

Поскольку vend(itemNamed: ) метод передает все ошибки, которые он генерирует, вызывающему его коду, то они должны быть обработаны напрямую, используя оператор do-catch, try? или try!, или должны быть переданы дальше. Например, buyFavoriteSnack(person:vendingMachine: ) в примере ниже — это тоже генерирующая функция, и любые ошибки, которые генерирует метод vend(itemNamed: ), будут переноситься до точки, где будет вызываться функция buyFavoriteSnack(person:vendingMachine: ).

let favoriteSnacks = [
    "Alice": "Chips",
    "Bob": "Licorice",
    "Eve": "Pretzels"
]
func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
    let snackName = favoriteSnacks[person] ?? "Candy Bar"
    try vendingMachine.vend(itemNamed: snackName)
}

В этом примере, функция buyFavoriteSnack(person:vendingMachine: ) подбирает любимые закуски данного человека и пытается их купить, вызывая vend(itemNamed: ) метод. Поскольку метод vend(itemNamed: ) может сгенерировать ошибку, он вызывается с ключевым словом try перед ним.

Генерирующие ошибку инициализаторы могут распространять ошибки таким же образом, как генерирующие ошибку функции. Например, инициализатор структуры PurchasedSnack в списке ниже вызывает генерирующую ошибку функции как часть процесса инициализации, и он обрабатывает любые ошибки, с которыми сталкивается, путем распространения их до вызывающего его объекта.

struct PurchasedSnack {
    let name: String
    init(name: String, vendingMachine: VendingMachine) throws {
        try vendingMachine.vend(itemNamed: name)
        self.name = name
    }
}

Обработка ошибок с использованием do-catch

Используйте инструкцию do-catch для обработки ошибок, запуская блок кода. Если выдается ошибка в коде условия do, она соотносится с условием catch для определения того, кто именно сможет обработать ошибку.

Вот общий вид условия do-catch:

do {
    try выражение
    выражение
} catch шаблон 1 {
    выражение
} catch шаблон 2  where условие {
    выражение
} catch шаблон 3, шаблон 4 where условие {
    выражение
} catch {
    выражение
}

Вы пишете шаблон после ключевого слова catch, чтобы указать какие ошибки могут обрабатываться данным пунктом этого обработчика. Если условие catch не имеет своего шаблона, то оно подходит под любые ошибки и связывает ошибки к локальной константе error. Более подробно о соответствии шаблону см. Шаблоны.

Например, следующий код обрабатывает все три случая в перечислении VendingMachineError, но все другие ошибки должны быть обработаны окружающей областью:

var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {
    try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
} catch VendingMachineError.invalidSelection {
    print("Ошибка выбора.")
} catch VendingMachineError.outOfStock {
    print("Нет в наличии.")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
    print("Недостаточно средств. Пожалуйста вставьте еще (coinsNeeded) монетки.")
} catch {
    print("Неожиданная ошибка: (error).")
}
// Выведет "Недостаточно средств. Пожалуйста вставьте еще 2 монетки.

В приведенном выше примере, buyFavoriteSnack(person:vendingMachine: ) функция вызывается в выражении try, потому что она может сгенерировать ошибку. Если генерируется ошибка, выполнение немедленно переносится в условия catch, которые принимают решение о продолжении передачи ошибки. Если ошибка не генерируется, остальные операторы do выполняются.

В условии catch не нужно обрабатывать все возможные ошибки, которые может вызвать код в условии do. Если ни одно из условий catch не обрабатывает ошибку, ошибка распространяется на окружающую область. Однако распространяемая ошибка должна обрабатываться некоторой внешней областью. В функции nonthrowing условие включения do-catch должно обрабатывать ошибку. В функции throwing либо включающая условие do-catch, либо вызывающая сторона должна обрабатывать ошибку. Если ошибка распространяется на область верхнего уровня без обработки, вы получите ошибку исполнения.

Например, приведенный ниже пример можно записать так, чтобы любая ошибка, которая не является VendingMachineError, вместо этого захватывалась вызывающей функцией:

func nourish(with item: String) throws {
    do {
        try vendingMachine.vend(itemNamed: item)
    } catch is VendingMachineError {
        print("Некорректный вывод, нет в наличии или недостаточно денег.")
    }
}

do {
    try nourish(with: "Beet-Flavored Chips")
} catch {
    print("Unexpected non-vending-machine-related error: (error)")
}
// Выведет "Некорректный вывод, нет в наличии или недостаточно денег."

В nourish(with: ), если vend(itemNamed : ) выдает ошибку, которая является одним из кейсов перечисления VendingMachineError, nourish(with: ) обрабатывает ошибку, печатая сообщение. В противном случае, nourish(with: ) распространяет ошибку на свое место вызова. Ошибка затем попадает в общее условие catch.

Преобразование ошибок в опциональные значения

Вы можете использовать try? для обработки ошибки, преобразовав ее в опциональное значение. Если ошибка генерируется при условии try?, то значение выражения вычисляется как nil. Например, в следующем коде x и y имеют одинаковые значения и поведение:

func someThrowingFunction() throws -> Int {
    // ...
}
 
let x = try? someThrowingFunction()
 
let y: Int?
do {
    y = try someThrowingFunction()
} catch {
    y = nil
}

Если someThrowingFunction() генерирует ошибку, значение x и y равно nil. В противном случае значение x и y — это возвращаемое значение функции. Обратите внимание, что x и y являются опциональными, независимо от того какой тип возвращает функция someThrowingFunction().

Использование try? позволяет написать краткий код обработки ошибок, если вы хотите обрабатывать все ошибки таким же образом. Например, следующий код использует несколько попыток для извлечения данных или возвращает nil, если попытки неудачные.

func fetchData() -> Data? {
    if let data = try? fetchDataFromDisk() { return data }
    if let data = try? fetchDataFromServer() { return data }
    return nil
}

Запрет на передачу ошибок

Иногда вы знаете, что функции throw или методы не сгенерируют ошибку во время исполнения. В этих случаях, вы можете написать try! перед выражением для запрета передачи ошибки и завернуть вызов в утверждение того, что ошибка точно не будет сгенерирована. Если ошибка на самом деле сгенерирована, вы получите сообщение об ошибке исполнения.

Например, следующий код использует loadImage(atPath: ) функцию, которая загружает ресурс изображения по заданному пути или генерирует ошибку, если изображение не может быть загружено. В этом случае, поскольку изображение идет вместе с приложением, сообщение об ошибке не будет сгенерировано во время выполнения, поэтому целесообразно отключить передачу ошибки.

let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")

Установка действий по очистке (Cleanup)

Вы используете оператор defer для выполнения набора инструкций перед тем как исполнение кода оставит текущий блок. Это позволяет сделать любую необходимую очистку, которая должна быть выполнена, независимо от того, как именно это произойдет — либо он покинет из-за сгенерированной ошибки или из-за оператора, такого как break или return. Например, вы можете использовать defer, чтобы удостовериться, что файл дескрипторов закрыт и выделенная память вручную освобождена.

Оператор defer откладывает выполнение, пока не происходит выход из текущей области. Этот оператор состоит из ключевого слова defer и выражений, которые должны быть выполнены позже. Отложенные выражения могут не содержать кода, изменяющего контроль исполнения изнутри наружу, при помощи таких операторов как break или return, или просто генерирующего ошибку. Отложенные действия выполняются в обратном порядке, как они указаны, то есть, код в первом операторе defer выполняется после кода второго, и так далее.

func processFile(filename: String) throws {
    if exists(filename) {
        let file = open(filename)
        defer {
            close(file)
        }
        while let line = try file.readline() {
            // работаем с файлом.
        }
        // close(file) вызывается здесь, в конце зоны видимости.
    }
}

Приведенный выше пример использует оператор defer, чтобы удостовериться, что функция open(_: ) имеет соответствующий вызов и для close(_: ).

Заметка

Вы можете использовать оператор defer, даже если не используете кода обработки ошибок.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Обработка ошибок — это процесс реагирования и исправления ошибок в вашей программе. Swift обеспечивает первоклассную поддержку для генерации, перехвата, распространения и обработки исправляемых ошибок во время выполнения.

Некоторые операции не всегда гарантируют завершение выполнения или получение полезного результата. Необязательные параметры используются для представления отсутствия значения, но когда происходит сбой операции, часто полезно понять, что вызвало сбой, чтобы ваш код мог реагировать соответствующим образом.

В качестве примера рассмотрим задачу чтения и обработки данных из файла на диске. Эта задача может быть выполнена несколькими способами, включая файл, не существующий по указанному пути, файл, не имеющий разрешений на чтение, или файл, не закодированный в совместимом формате. Различение между этими различными ситуациями позволяет программе устранять некоторые ошибки и сообщать пользователю о любых ошибках, которые она не может устранить.

ЗАМЕТКА

Обработка ошибок в Swift взаимодействует с шаблонами обработки ошибок, которые используют NSErrorкласс в Какао и Objective-C. 

Представление и бросание ошибок

В Swift ошибки представлены значениями типов, которые соответствуют Errorпротоколу. Этот пустой протокол указывает, что тип может использоваться для обработки ошибок.

Перечисления Swift особенно хорошо подходят для моделирования группы связанных состояний ошибок с соответствующими значениями, позволяющими передавать дополнительную информацию о природе ошибки. Например, вот как вы можете представить условия ошибки работы торгового автомата в игре:

enum VendingMachineError: Error {
    case invalidSelection
    case insufficientFunds(coinsNeeded: Int)
    case outOfStock
}

Выдача ошибки позволяет вам указать, что произошло что-то неожиданное, и нормальный поток выполнения не может продолжаться. Вы используете throwзаявление, чтобы выбросить ошибку. Например, следующий код выдает ошибку, чтобы указать, что торговому автомату необходимо пять дополнительных монет:

throw VendingMachineError.insufficientFunds(coinsNeeded: 5)

Обработка ошибок

Когда выдается ошибка, некоторый окружающий фрагмент кода должен отвечать за обработку ошибки — например, путем исправления проблемы, попытки альтернативного подхода или информирования пользователя о сбое.

Существует четыре способа обработки ошибок в Swift. Вы можете распространять ошибку из функции в код, который вызывает эту функцию, обрабатывать ошибку с помощью оператора do— catch, обрабатывать ошибку как необязательное значение или утверждать, что ошибка не произойдет. Каждый подход описан в разделе ниже.

Когда функция выдает ошибку, она меняет поток вашей программы, поэтому важно, чтобы вы могли быстро определить места в вашем коде, которые могут выдавать ошибки. Чтобы определить эти места в вашем коде, напишите tryключевое слово ( try?или try!вариант или) перед фрагментом кода, который вызывает функцию, метод или инициализатор, который может вызвать ошибку. Эти ключевые слова описаны в разделах ниже.

ЗАМЕТКА

Обработка ошибок в Swift напоминает обработку исключений в других языках, с использованием trycatchи throwключевых слов. В отличие от обработки исключений во многих языках, включая Objective-C, обработка ошибок в Swift не включает в себя разматывание стека вызовов, процесс, который может быть вычислительно дорогим. Таким образом, рабочие характеристики throwоператора сопоставимы с характеристиками returnоператора.

Распространение ошибок с использованием бросающих функций

Чтобы указать, что функция, метод или инициализатор могут выдать ошибку, вы пишете throwsключевое слово в объявлении функции после ее параметров. Функция с пометкой throwsназывается функцией броска . Если функция указывает тип возвращаемого значения, вы пишете throwsключевое слово перед стрелкой возврата ( ->).

func canThrowErrors() throws -> String

func cannotThrowErrors() -> String

Функция выброса распространяет ошибки, которые выбрасываются внутри нее, в область, из которой она вызывается.

ЗАМЕТКА

Только бросающие функции могут распространять ошибки. Любые ошибки, возникающие в неработающей функции, должны обрабатываться внутри функции.

В приведенном ниже примере VendingMachineкласс имеет vend(itemNamed:)метод, который выбрасывает соответствующее значение, VendingMachineErrorесли запрошенный элемент недоступен, отсутствует на складе или имеет стоимость, превышающую текущую сумму депозита:

struct Item {
    var price: Int
    var count: Int
}
 
class VendingMachine {
    var inventory = [
        "Candy Bar": Item(price: 12, count: 7),
        "Chips": Item(price: 10, count: 4),
        "Pretzels": Item(price: 7, count: 11)
    ]
    var coinsDeposited = 0
    
    func vend(itemNamed name: String) throws {
        guard let item = inventory[name] else {
            throw VendingMachineError.invalidSelection
        }
        
        guard item.count > 0 else {
            throw VendingMachineError.outOfStock
        }
        
        guard item.price <= coinsDeposited else {
            throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
        }
        
        coinsDeposited -= item.price
        
        var newItem = item
        newItem.count -= 1
        inventory[name] = newItem
        
        print("Dispensing (name)")
    }
}

Реализация vend(itemNamed:)метода использует guardоператоры для раннего выхода из метода и выдачи соответствующих ошибок, если какое-либо из требований для покупки закуски не выполнено. Поскольку throwоператор немедленно передает управление программой, элемент будет продаваться, только если все эти требования будут выполнены.

Поскольку vend(itemNamed:)метод распространяется любые ошибки , он бросает, любой код , который вызывает этот метод должен либо обрабатывать ошибки, используя do— catchзаявление, try?или try!-или продолжают их распространять. Например, buyFavoriteSnack(person:vendingMachine:)в приведенном ниже примере также есть функция throwing, и любые ошибки, которые vend(itemNamed:)генерирует метод, будут распространяться вплоть до точки, где buyFavoriteSnack(person:vendingMachine:)вызывается функция.

let favoriteSnacks = [

"Alice": "Chips",

"Bob": "Licorice",

"Eve": "Pretzels",

]

func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {

let snackName = favoriteSnacks[person] ?? "Candy Bar"

try vendingMachine.vend(itemNamed: snackName)

}

В этом примере функция ищет любимую закуску данного человека и пытается купить ее, вызвав метод. Поскольку метод может выдать ошибку, он вызывается с ключевым словом перед ним.buyFavoriteSnack(person: vendingMachine:)vend(itemNamed:)vend(itemNamed:)try

Бросающие инициализаторы могут распространять ошибки так же, как и бросающие функции. Например, инициализатор для PurchasedSnackструктуры в приведенном ниже листинге вызывает функцию выброса как часть процесса инициализации и обрабатывает любые возникающие ошибки, передавая их вызывающей стороне.

struct PurchasedSnack {

let name: String

init(name: String, vendingMachine: VendingMachine) throws {

try vendingMachine.vend(itemNamed: name)

self.name = name

}

}

Обработка ошибок с помощью Do-Catch

Вы используете оператор do— catchдля обработки ошибок, выполняя блок кода. Если код в doпредложении выдает ошибку , он сопоставляется с catchпредложениями, чтобы определить, какой из них может обработать ошибку.

Вот общая форма do— catchзаявление:

do {

try expression

statements

} catch pattern 1 {

statements

} catch pattern 2 where condition {

statements

} catch {

statements

}

Вы пишете шаблон после, catchчтобы указать, какие ошибки может обработать это предложение. Если catchпредложение не имеет шаблона, оно сопоставляется с любой ошибкой и связывает ошибку с локальной константой с именем error

Например, следующий код соответствует всем трем случаям VendingMachineErrorперечисления.

var vendingMachine = VendingMachine()

vendingMachine.coinsDeposited = 8

do {

try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)

print("Success! Yum.")

} catch VendingMachineError.invalidSelection {

print("Invalid Selection.")

} catch VendingMachineError.outOfStock {

print("Out of Stock.")

} catch VendingMachineError.insufficientFunds(let coinsNeeded) {

print("Insufficient funds. Please insert an additional (coinsNeeded) coins.")

} catch {

print("Unexpected error: (error).")

}

// Prints "Insufficient funds. Please insert an additional 2 coins."

В приведенном выше примере buyFavoriteSnack(person:vendingMachine:)функция вызывается в tryвыражении, поскольку она может выдать ошибку. Если выдается ошибка, выполнение немедленно переходит к catchпредложениям, которые решают, следует ли продолжить распространение. Если ни один шаблон не сопоставлен, ошибка попадает в заключительное catchпредложение и связывается с локальной errorконстантой. Если ошибка не выдана, остальные операторы в doоператоре выполняются.

Предложения catchне должны обрабатывать каждую возможную ошибку, которую doможет выдать код в предложении. Если ни одно из catchпредложений не обрабатывает ошибку, ошибка распространяется на окружающую область. Однако распространяемая ошибка должна быть обработана некоторой окружающей областью. В функции nonthrowing, объемлющий do— catchпункт должен обработать ошибку. В функции метательного, либо вшита do— catchпункт или вызывающий должен обработать ошибку. Если ошибка распространяется на область верхнего уровня без обработки, вы получите ошибку во время выполнения.

Например, приведенный выше пример может быть написан так, что любая ошибка, которая не VendingMachineErrorявляется, вместо этого перехватывается вызывающей функцией:

func nourish(with item: String) throws {

do {

try vendingMachine.vend(itemNamed: item)

} catch is VendingMachineError {

print("Invalid selection, out of stock, or not enough money.")

}

}



do {

try nourish(with: "Beet-Flavored Chips")

} catch {

print("Unexpected non-vending-machine-related error: (error)")

}

// Prints "Invalid selection, out of stock, or not enough money."

В nourish(with:)функции, если vend(itemNamed:)выдает ошибку, которая является одним из случаев VendingMachineErrorперечисления, nourish(with:)обрабатывает ошибку, печатая сообщение. В противном случае nourish(with:)распространяет ошибку на свой сайт вызова. Ошибка тогда поймана общим catchпредложением.

Преобразование ошибок в необязательные значения

Вы используете try?для обработки ошибки путем преобразования ее в необязательное значение. Если при вычислении try?выражения выдается ошибка , значением выражения является nil. Например, в следующем коде xи yимеют то же значение и поведение:

func someThrowingFunction() throws -> Int {
    // ...
}
 
let x = try? someThrowingFunction()
 
let y: Int?
do {
    y = try someThrowingFunction()
} catch {
    y = nil
}

Если someThrowingFunction()выдает ошибку, значение xи yесть nil. В противном случае значение xи yявляется значением, которое вернула функция. Обратите внимание, что xи yявляются необязательными для любого типа someThrowingFunction()возврата. Здесь функция возвращает целое число, поэтому xи yявляются необязательными целыми числами.

Использование try?позволяет вам написать краткий код обработки ошибок, когда вы хотите обрабатывать все ошибки одинаково. Например, следующий код использует несколько подходов для извлечения данных или возвращает, nilесли все подходы дают сбой.

func fetchData() -> Data? {

if let data = try? fetchDataFromDisk() { return data }

if let data = try? fetchDataFromServer() { return data }

return nil

}

Отключение распространения ошибок

Иногда вы знаете, что бросающая функция или метод на самом деле не будут выдавать ошибку во время выполнения. В таких случаях вы можете написать try!перед выражением, чтобы отключить распространение ошибок, и обернуть вызов в утверждение времени выполнения, что не будет выдано никакой ошибки. Если на самом деле выдается ошибка, вы получите ошибку во время выполнения.

Например, в следующем коде используется loadImage(atPath:)функция, которая загружает ресурс изображения по заданному пути или выдает ошибку, если изображение не может быть загружено. В этом случае, поскольку образ поставляется с приложением, во время выполнения не будет выдано никаких ошибок, поэтому целесообразно отключить распространение ошибок.

let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")

Указание действий по очистке

Вы используете deferоператор для выполнения набора операторов непосредственно перед тем, как выполнение кода покидает текущий блок кода. Этот оператор позволяет выполнять любую необходимую очистку, которая должна выполняться независимо от того, как выполнение покидает текущий блок кода — независимо от того, была ли вызвана ошибка или из-за оператора, такого как returnили break. Например, вы можете использовать deferинструкцию, чтобы гарантировать, что файловые дескрипторы закрыты, а выделенная вручную память освобождена.

deferЗаявление отсрочивает выполнение , пока текущая область не закрывается. Этот оператор состоит из deferключевого слова и операторов, которые будут выполнены позже. Отложенные операторы могут не содержать какой-либо код, который передавал бы управление из операторов, таких как оператор a breakили return, или путем выдачи ошибки. Отложенные действия выполняются в порядке, обратном порядку их написания в исходном коде. То есть код в первом deferоператоре выполняется последним, код во втором deferоператоре выполняется со второго до последнего и так далее. Последний deferоператор в порядке исходного кода выполняется первым.

func processFile(filename: String) throws {

if exists(filename) {

let file = open(filename)

defer {

close(file)

}

while let line = try file.readline() {

// Work with the file.

}

// close(file) is called here, at the end of the scope.

}

}

В приведенном выше примере используется deferоператор, чтобы гарантировать, что open(_:)функция имеет соответствующий вызов close(_:).

ЗАМЕТКА

Вы можете использовать deferоператор, даже если код обработки ошибок не используется.

Error handling is the process of responding to and recovering from error conditions in your program. Swift provides first-class support for throwing, catching, propagating, and manipulating recoverable errors at runtime.

Some operations aren’t guaranteed to always complete execution or produce a useful output. Optionals are used to represent the absence of a value, but when an operation fails, it’s often useful to understand what caused the failure, so that your code can respond accordingly.

As an example, consider the task of reading and processing data from a file on disk. There are a number of ways this task can fail, including the file not existing at the specified path, the file not having read permissions, or the file not being encoded in a compatible format. Distinguishing among these different situations allows a program to resolve some errors and to communicate to the user any errors it can’t resolve.

Representing and Throwing Errors¶

In Swift, errors are represented by values of types that conform to the Error protocol. This empty protocol indicates that a type can be used for error handling.

Swift enumerations are particularly well suited to modeling a group of related error conditions, with associated values allowing for additional information about the nature of an error to be communicated. For example, here’s how you might represent the error conditions of operating a vending machine inside a game:

  1. enum VendingMachineError: Error {
  2. case invalidSelection
  3. case insufficientFunds(coinsNeeded: Int)
  4. case outOfStock
  5. }

Throwing an error lets you indicate that something unexpected happened and the normal flow of execution can’t continue. You use a throw statement to throw an error. For example, the following code throws an error to indicate that five additional coins are needed by the vending machine:

  1. throw VendingMachineError.insufficientFunds(coinsNeeded: 5)

Handling Errors¶

When an error is thrown, some surrounding piece of code must be responsible for handling the error—for example, by correcting the problem, trying an alternative approach, or informing the user of the failure.

There are four ways to handle errors in Swift. You can propagate the error from a function to the code that calls that function, handle the error using a docatch statement, handle the error as an optional value, or assert that the error will not occur. Each approach is described in a section below.

When a function throws an error, it changes the flow of your program, so it’s important that you can quickly identify places in your code that can throw errors. To identify these places in your code, write the try keyword—or the try? or try! variation—before a piece of code that calls a function, method, or initializer that can throw an error. These keywords are described in the sections below.

Note

Error handling in Swift resembles exception handling in other languages, with the use of the try, catch and throw keywords. Unlike exception handling in many languages—including Objective-C—error handling in Swift doesn’t involve unwinding the call stack, a process that can be computationally expensive. As such, the performance characteristics of a throw statement are comparable to those of a return statement.

Propagating Errors Using Throwing Functions¶

To indicate that a function, method, or initializer can throw an error, you write the throws keyword in the function’s declaration after its parameters. A function marked with throws is called a throwing function. If the function specifies a return type, you write the throws keyword before the return arrow (->).

  1. func canThrowErrors() throws -> String
  2. func cannotThrowErrors() -> String

A throwing function propagates errors that are thrown inside of it to the scope from which it’s called.

Note

Only throwing functions can propagate errors. Any errors thrown inside a nonthrowing function must be handled inside the function.

In the example below, the VendingMachine class has a vend(itemNamed:) method that throws an appropriate VendingMachineError if the requested item isn’t available, is out of stock, or has a cost that exceeds the current deposited amount:

  1. struct Item {
  2. var price: Int
  3. var count: Int
  4. }
  5. class VendingMachine {
  6. var inventory = [
  7. «Candy Bar»: Item(price: 12, count: 7),
  8. «Chips»: Item(price: 10, count: 4),
  9. «Pretzels»: Item(price: 7, count: 11)
  10. ]
  11. var coinsDeposited = 0
  12. func vend(itemNamed name: String) throws {
  13. guard let item = inventory[name] else {
  14. throw VendingMachineError.invalidSelection
  15. }
  16. guard item.count > 0 else {
  17. throw VendingMachineError.outOfStock
  18. }
  19. guard item.price <= coinsDeposited else {
  20. throw VendingMachineError.insufficientFunds(coinsNeeded: item.pricecoinsDeposited)
  21. }
  22. coinsDeposited -= item.price
  23. var newItem = item
  24. newItem.count -= 1
  25. inventory[name] = newItem
  26. print(«Dispensing (name)«)
  27. }
  28. }

The implementation of the vend(itemNamed:) method uses guard statements to exit the method early and throw appropriate errors if any of the requirements for purchasing a snack aren’t met. Because a throw statement immediately transfers program control, an item will be vended only if all of these requirements are met.

Because the vend(itemNamed:) method propagates any errors it throws, any code that calls this method must either handle the errors—using a docatch statement, try?, or try!—or continue to propagate them. For example, the buyFavoriteSnack(person:vendingMachine:) in the example below is also a throwing function, and any errors that the vend(itemNamed:) method throws will propagate up to the point where the buyFavoriteSnack(person:vendingMachine:) function is called.

  1. let favoriteSnacks = [
  2. «Alice»: «Chips»,
  3. «Bob»: «Licorice»,
  4. «Eve»: «Pretzels»,
  5. ]
  6. func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
  7. let snackName = favoriteSnacks[person] ?? «Candy Bar»
  8. try vendingMachine.vend(itemNamed: snackName)
  9. }

In this example, the buyFavoriteSnack(person: vendingMachine:) function looks up a given person’s favorite snack and tries to buy it for them by calling the vend(itemNamed:) method. Because the vend(itemNamed:) method can throw an error, it’s called with the try keyword in front of it.

Throwing initializers can propagate errors in the same way as throwing functions. For example, the initializer for the PurchasedSnack structure in the listing below calls a throwing function as part of the initialization process, and it handles any errors that it encounters by propagating them to its caller.

  1. struct PurchasedSnack {
  2. let name: String
  3. init(name: String, vendingMachine: VendingMachine) throws {
  4. try vendingMachine.vend(itemNamed: name)
  5. self.name = name
  6. }
  7. }

Handling Errors Using Do-Catch¶

You use a docatch statement to handle errors by running a block of code. If an error is thrown by the code in the do clause, it’s matched against the catch clauses to determine which one of them can handle the error.

Here is the general form of a docatch statement:

  1. do {
  2. try expression
  3. statements
  4. } catch pattern 1 {
  5. statements
  6. } catch pattern 2 where condition {
  7. statements
  8. } catch pattern 3, pattern 4 where condition {
  9. statements
  10. } catch {
  11. statements
  12. }

You write a pattern after catch to indicate what errors that clause can handle. If a catch clause doesn’t have a pattern, the clause matches any error and binds the error to a local constant named error. For more information about pattern matching, see Patterns.

For example, the following code matches against all three cases of the VendingMachineError enumeration.

  1. var vendingMachine = VendingMachine()
  2. vendingMachine.coinsDeposited = 8
  3. do {
  4. try buyFavoriteSnack(person: «Alice», vendingMachine: vendingMachine)
  5. print(«Success! Yum.»)
  6. } catch VendingMachineError.invalidSelection {
  7. print(«Invalid Selection.»)
  8. } catch VendingMachineError.outOfStock {
  9. print(«Out of Stock.»)
  10. } catch VendingMachineError.insufficientFunds(let coinsNeeded) {
  11. print(«Insufficient funds. Please insert an additional (coinsNeeded) coins.»)
  12. } catch {
  13. print(«Unexpected error: (error))
  14. }
  15. // Prints «Insufficient funds. Please insert an additional 2 coins.»

In the above example, the buyFavoriteSnack(person:vendingMachine:) function is called in a try expression, because it can throw an error. If an error is thrown, execution immediately transfers to the catch clauses, which decide whether to allow propagation to continue. If no pattern is matched, the error gets caught by the final catch clause and is bound to a local error constant. If no error is thrown, the remaining statements in the do statement are executed.

The catch clauses don’t have to handle every possible error that the code in the do clause can throw. If none of the catch clauses handle the error, the error propagates to the surrounding scope. However, the propagated error must be handled by some surrounding scope. In a nonthrowing function, an enclosing docatch statement must handle the error. In a throwing function, either an enclosing docatch statement or the caller must handle the error. If the error propagates to the top-level scope without being handled, you’ll get a runtime error.

For example, the above example can be written so any error that isn’t a VendingMachineError is instead caught by the calling function:

  1. func nourish(with item: String) throws {
  2. do {
  3. try vendingMachine.vend(itemNamed: item)
  4. } catch is VendingMachineError {
  5. print(«Couldn’t buy that from the vending machine.»)
  6. }
  7. }
  8. do {
  9. try nourish(with: «Beet-Flavored Chips»)
  10. } catch {
  11. print(«Unexpected non-vending-machine-related error: (error)«)
  12. }
  13. // Prints «Couldn’t buy that from the vending machine.»

In the nourish(with:) function, if vend(itemNamed:) throws an error that’s one of the cases of the VendingMachineError enumeration, nourish(with:) handles the error by printing a message. Otherwise, nourish(with:) propagates the error to its call site. The error is then caught by the general catch clause.

Another way to catch several related errors is to list them after catch, separated by commas. For example:

  1. func eat(item: String) throws {
  2. do {
  3. try vendingMachine.vend(itemNamed: item)
  4. } catch VendingMachineError.invalidSelection, VendingMachineError.insufficientFunds, VendingMachineError.outOfStock {
  5. print(«Invalid selection, out of stock, or not enough money.»)
  6. }
  7. }

The eat(item:) function lists the vending machine errors to catch, and its error text corresponds to the items in that list. If any of the three listed errors are thrown, this catch clause handles them by printing a message. Any other errors are propagated to the surrounding scope, including any vending-machine errors that might be added later.

Converting Errors to Optional Values¶

You use try? to handle an error by converting it to an optional value. If an error is thrown while evaluating the try? expression, the value of the expression is nil. For example, in the following code x and y have the same value and behavior:

  1. func someThrowingFunction() throws -> Int {
  2. // …
  3. }
  4. let x = try? someThrowingFunction()
  5. let y: Int?
  6. do {
  7. y = try someThrowingFunction()
  8. } catch {
  9. y = nil
  10. }

If someThrowingFunction() throws an error, the value of x and y is nil. Otherwise, the value of x and y is the value that the function returned. Note that x and y are an optional of whatever type someThrowingFunction() returns. Here the function returns an integer, so x and y are optional integers.

Using try? lets you write concise error handling code when you want to handle all errors in the same way. For example, the following code uses several approaches to fetch data, or returns nil if all of the approaches fail.

  1. func fetchData() -> Data? {
  2. if let data = try? fetchDataFromDisk() { return data }
  3. if let data = try? fetchDataFromServer() { return data }
  4. return nil
  5. }

Disabling Error Propagation¶

Sometimes you know a throwing function or method won’t, in fact, throw an error at runtime. On those occasions, you can write try! before the expression to disable error propagation and wrap the call in a runtime assertion that no error will be thrown. If an error actually is thrown, you’ll get a runtime error.

For example, the following code uses a loadImage(atPath:) function, which loads the image resource at a given path or throws an error if the image can’t be loaded. In this case, because the image is shipped with the application, no error will be thrown at runtime, so it’s appropriate to disable error propagation.

  1. let photo = try! loadImage(atPath: «./Resources/John Appleseed.jpg»)

Specifying Cleanup Actions¶

You use a defer statement to execute a set of statements just before code execution leaves the current block of code. This statement lets you do any necessary cleanup that should be performed regardless of how execution leaves the current block of code—whether it leaves because an error was thrown or because of a statement such as return or break. For example, you can use a defer statement to ensure that file descriptors are closed and manually allocated memory is freed.

A defer statement defers execution until the current scope is exited. This statement consists of the defer keyword and the statements to be executed later. The deferred statements may not contain any code that would transfer control out of the statements, such as a break or a return statement, or by throwing an error. Deferred actions are executed in the reverse of the order that they’re written in your source code. That is, the code in the first defer statement executes last, the code in the second defer statement executes second to last, and so on. The last defer statement in source code order executes first.

  1. func processFile(filename: String) throws {
  2. if exists(filename) {
  3. let file = open(filename)
  4. defer {
  5. close(file)
  6. }
  7. while let line = try file.readline() {
  8. // Work with the file.
  9. }
  10. // close(file) is called here, at the end of the scope.
  11. }
  12. }

The above example uses a defer statement to ensure that the open(_:) function has a corresponding call to close(_:).

Note

You can use a defer statement even when no error handling code is involved.

Мы используем обработку ошибок с помощью do-try-catch для реагирования на исправимые ошибки. Это дает нам больший контроль над различными ошибочными сценариями, которые могут возникнуть в нашем коде, например, при вводе неправильного имени пользователя или пароля.

Зачем нужно отслеживать ошибки?

В приложении некоторые ошибки могут быть результатом ошибок программиста. Когда ваше приложение вылетает с сообщением «Index out of bounds», вы, вероятно, где-то допустили ошибку. И точно так же, когда вы принудительно извлекаете опциональное значение, которое имеет значение nil, ваше приложение падает.

В практической разработке iOS некоторые ошибки являются частью работы приложения, например, сообщение «Недостаточно средств» при попытке оплаты с помощью карты.

Ошибки такого рода исправимы. Их можно обработать и отреагировать соответствующим образом. К примеру:

  • При попытке снять деньги в банкомате отображается «Неверный PIN-код».
  • Ваш автомобиль показывает индикатор низкого уровня топлива при попытке запустить двигатель.
  • Попытка аутентификации для API возвращает «Неверное имя пользователя / пароль».

Вы можете работать с этими ошибками, отобразив сообщение с предупреждением или сделав что-то еще. Например, ваша карта блокируется после 3 неудачных попыток. Ваш автомобиль может указать вам ближайшую заправку, когда у вас кончается бензин. Вы можете попробовать ввести другое имя пользователя и пароль.

Swift поддерживает обработку ошибок с помощью блока кода do-try-catch.

Выбрасывание ошибок

Когда в вашем коде возникает сценарий, который может привести к ошибке, вы можете выбросить ошибку:

if fuel < 1000 {
    throw RocketError.insufficientFuel
}

В приведенном выше коде ключевое слово throw используется для выдачи ошибки типа RocketError.insufficientFuel, когда переменная fuel меньше, чем 1000.

Представьте, что мы пытаемся запустить ракету:

func igniteRockets(fuel: Int, astronauts: Int) throws {
    if fuel < 1000 {
        throw RocketError.insufficientFuel
    }
    else if astronauts < 3 {
        throw RocketError.insufficientAstronauts(needed: 3)
    }
 
    // Запуск ракеты
    print("3... 2... 1... Старт!")
}

Функция igniteRockets(fuel:astronauts:) будет запускать ракеты, только если значение fuel больше или равно 1000 и если на борту есть как минимум 3 астронавта.

Функция igniteRockets(…) также помечается ключевым словом throws. Это ключевое слово указывает, что ошибки должны быть обработаны.

В приведенном выше коде мы используем тип ошибки RocketError:

enum RocketError: Error {
    case insufficientFuel
    case insufficientAstronauts(needed: Int)
    case unknownError
}

Данное перечисление определяет три типа ошибок: .insufficientFuel, insufficientAstronauts(needed) и .unknownError. Определение ваших собственных типов ошибок полезно, потому что это поможет четко понять, что эти ошибки означают в вашем коде.

Возьмем, например, ошибку insufficientAstronauts(needed:). Когда выдается эта ошибка, вы можете использовать аргумент needed:, который указывает, сколько астронавтов необходимо для успешного запуска ракеты.

Ключевое слово throw имеет тот же эффект, что и ключевое слово return. Когда выполняется throw, выполнение функции останавливается, и выброшенная ошибка передается вызывающей функции.

Теперь мы можем использовать обработку ошибок, чтобы соответствующим образом реагировать на сценарии ошибок. Обработка ошибок в Swift осуществляется с помощью блока кода do-try-catch:

do {
    try igniteRockets(fuel: 5000, astronauts: 1)    
} catch {
    print(error)
}

Обработка ошибок имеет три аспекта:

  • К функции, которая может вызвать ошибку, добавляется ключевое слово try.
  • Блок кода, который включает ключевое слово try, обернут в do { … }.
  • Один или несколько блоков catch { … } могут быть присоединены к do { … } для обработки отдельных случаев ошибок.

Если функция выдает ошибку, вызывается блок catch. В данном случае это выводит ошибку на консоль.

Вы также можете реагировать на ошибки в индивидуальном порядке:

do {
    try igniteRockets(fuel: 5000, astronauts: 1)    
} catch RocketError.insufficientFuel {
    print("Ракете нужно больше топлива!")
} catch RocketError.insufficientAstronauts(let needed) {
    print("Нужно как минимум (needed) астронавта...")
}

Вышеуказанные блоки catch вызываются на основании отдельных перечислений RocketError. Вы можете напрямую получить доступ к связанным значениям перечислений, таких как needed. Также вы можете использовать выражения с шаблоном where чтобы получить больший контроль над ошибочным сценарием.

enum RocketError: Error {
    case insufficientFuel
    case insufficientAstronauts(needed: Int)
    case unknownError
}
 
func igniteRockets(fuel: Int, astronauts: Int) throws {
    if fuel < 1000 {
        throw RocketError.insufficientFuel
    }
    else if astronauts < 3 {
        throw RocketError.insufficientAstronauts(needed: 3)
    }
 
    // Ignite rockets
    print("3... 2... 1... Полет!")
}
 
do {
    try igniteRockets(fuel: 5000, astronauts: 1)
} catch {
    print(error)
}

Преобразование ошибок в опционалы с помощью try?

Целью обработки ошибок является явное определение того, что происходит при возникновении ошибки. Это позволяет нам реагировать определенным образом на ошибки.

В некоторых случаях нас не волнует сама ошибка. Нам просто нужно получить значение из функции. И если возникает ошибка, мы можем возвратить nil. Эта возможность доступна с помощью ключевого слова try? Когда вы используете try?, вам не нужно использовать полный блок кода do-try-catch.

let result = try? calculateValue(for: 42)

Представьте, что функция может выбрасывать ошибки, если ее параметр недействителен. Вместо обработки ошибки мы конвертируем возвращаемое значение в опциональное.

Возможны два сценария:

  • Функция не выдает ошибку и возвращает значение, которое присваивается константе result.
  • Функция выдает ошибку и не возвращает значение. Это означает, что константе result присваивается nil.

Обработка ошибок с помощью try? означает, что вы можете воспользоваться синтаксисом, специфичным для опционалов, таких как объединение по nil и опциональное связывание:

if let result = try? calculateValue(for: 99) {
    // 
}
 
let result = try? calculateValue(for: 123) ?? 101

Отключение обработки ошибок с помощью try!

Вы можете полностью отключить обработку ошибок с помощью try!. Ключевое слово try! используется для принудиального извлечения опционального значения.

В отличие от того try?, который возвращает опциональное значение, синтаксис try! приведет к сбою вашего кода в случае возникновения ошибки. Есть два различных сценария, в которых использование try! может быть полезно:

  • Используйте try!, когда вы на 100% уверенны, что ошибка не возникнет.
  • Используйте, try!, когда невозможно продолжить выполнение кода.

Представьте, что вы пишите приложение, в которое встроен файл базы данных. Функция загрузки базы данных выдает ошибку, когда база данных повреждена. Вы можете использовать try! для загрузки базы данных в память, потому что, если база данных повреждена, приложение все равно не сможет быть использовано.

Search code, repositories, users, issues, pull requests…

Provide feedback

Saved searches

Use saved searches to filter your results more quickly

Sign up

  • Messaging

    FIN

    Error CodesThis reference guide lists the error codes and abort
    notifications returned by FIN in case of message validation errors
    orother conditions such as protocol violations or delivery
    issues.

    22 July 2011

  • Table of Contents

    Preface………………………………………………………………………………………………………………………………….
    4

    About this document
    ……………………………………………………………………………………………………………
    4

    Audience
    ……………………………………………………………………………………………………………………………
    4

    Significant
    changes……………………………………………………………………………………………………………..
    4

    Chapter 1 Introduction
    …………………………………………………………………………………………………………….
    6

    Chapter 2 Numeric Codes
    ……………………………………………………………………………………………………….
    7

    2.1 General
    ………………………………………………………………………………………………………………………..
    7

    2.2 Logout/Quit Acknowledgement Errors
    ………………………………………………………………………………
    7

    2.3 Re-Login Request Errors
    ………………………………………………………………………………………………..
    7

    2.4 Retrieval Errors
    ……………………………………………………………………………………………………………..
    8

    2.5 Message Status
    …………………………………………………………………………………………………………..
    10

    2.6 Abort Reasons
    …………………………………………………………………………………………………………….
    12

    2.7 FIN and General Purpose Application Session
    Termination……………………………………………….
    13

    2.8 Report Errors
    ………………………………………………………………………………………………………………
    14

    2.9 Bulk Retrieval Errors
    Codes…………………………………………………………………………………………..
    15

    Chapter 3 Alphanumeric
    Codes………………………………………………………………………………………………
    16

    3.1 General
    ………………………………………………………………………………………………………………………
    16

    3.2 A Codes — Re-select Error Codes
    …………………………………………………………………………………..
    16

    3.3 B Codes — Copy Service
    Errors………………………………………………………………………………………
    16

    3.4 C, D, and E Codes — Conditional Semantic Error Codes
    …………………………………………………… 17

    3.5 G Codes — Service-specific
    Validation……………………………………………………………………………
    156

    3.6 H Codes — Basic Header and Application Header Validation
    ……………………………………………. 158

    3.7 K Codes — Code Words Validation in Generic Fields
    ……………………………………………………….
    159

    3.8 L Codes — LOGIN Errors
    ……………………………………………………………………………………………..
    160

    3.9 M Codes — Message Errors
    ………………………………………………………………………………………….
    160

    3.10 P Codes — Protocol Errors
    ………………………………………………………………………………………….
    161

    3.11 R Codes — Re-login/Re-select Errors
    …………………………………………………………………………..
    162

    3.12 S Codes — System-initiated Abort Errors
    ………………………………………………………………………
    162

    3.13 S Codes — Select Errors
    …………………………………………………………………………………………….
    163

    3.14 T Codes — Text Validation
    ………………………………………………………………………………………….
    165

    3.15 U Codes — User Header
    Validation………………………………………………………………………………
    180

    3.16 V Codes — System Message Errors and Message Block Format
    Errors …………………………… 180

    3.17 X Codes — FINCopy Message Validation (01 — 27) and Delayed
    NAK Error Codes (30 — 99) . 183

    FIN

    2 Error Codes

  • 3.18 Y Codes — UNK Error Codes
    ………………………………………………………………………………………
    185

    3.19 Z Codes — Trailer Validation
    ……………………………………………………………………………………….
    185

    Chapter 4 FIN
    Errors……………………………………………………………………………………………………………
    186

    4.1 Introduction
    ……………………………………………………………………………………………………………….
    186

    4.2 Abort Codes
    ………………………………………………………………………………………………………………
    186

    4.3 Diagnostic Codes for
    SS100………………………………………………………………………………………..
    188

    4.4 Diagnostic Codes for
    SA100………………………………………………………………………………………..
    190

    Legal Notices
    ……………………………………………………………………………………………………………………..
    194

    Table of Contents

    22 July 2011 3

  • Preface

    About this documentThis reference guide lists the error codes
    and abort notifications returned by FIN in case of message
    validationerrors or other conditions such as protocol violations or
    delivery issues.

    AudienceThis book describes the FIN Error Codes. It should be
    read by:

    users who wish to gain an understanding of the FIN service

    developers who need background information on elements of
    FIN

    The reader is expected to have an understanding of FIN
    messaging, which is described in the FIN ServiceDescription and the
    FIN Operations Guide.

    Significant changesThe following tables list all significant
    changes to the content of the FIN Error Codes since the 23 July
    2010edition. These tables do not include editorial changes that
    SWIFT makes to improve the usability andcomprehension of the
    document.

    New information Location

    Addition of MTs 670 in error codes C05, D08, D09,D11, D12, D13,
    D14, D15, E23, E84, T19, T73, T85,and T86

    Error codes C05, D08, D09, D11, D12, D13, D14,D15, E23, E84,
    T19, T73, T85, and T86

    Addition of MTs 380 and 381 in error code D13 Error code D13

    Addition of message status 29 Section 2.5, Message Status

    Addition of abort reason code 29 Section 2.6, Abort Reasons

    Explanation regarding code S1 Section 2.6, Abort Reasons

    Addition of report errors 006, 007, 008, 009, and 016 Section
    2.8, Report Errors

    Addition of error codes M78, M79, M80, and M81 Section 3.9, M
    Codes — Message Errors

    New FIN errors chapter Chapter 4, FIN Errors

    Updated information Location

    Update text of message statuses 31, 32, 33, 34, 35,37, 38

    Section 2.5, Message Status

    FIN

    4 Error Codes

  • Updated information Location

    Update text of error codes B03, C28, C59, C71, E06,E08, E09,
    E22, E62, E77, E78, E80, E83, E87, E98,M73, T14, T39, T62, T73, and
    U03

    Section 3.3, B Codes — Copy Service Errors

    Section 3.4.1, C Error Codes

    Section 3.4.3, E Error Codes

    Section 3.9, M Codes — Message Errors

    Section 3.14, T Codes — Text Validation

    Section 3.15, U Codes — User Header Validation

    Error codes D87, D88, D89, D90, D91, D94, D95,E63, E75, E88,
    E89, E98, and V26 again available Section 3.4.2, D Error Codes

    Section 3.4.3, E Error Codes

    Section 3.16, V Codes — System Message Errorsand Message Block
    Format Errors

    Deleted information Location

    Deletion of references to MTs 405, 528, 529, 582,584, 587, 588,
    and 589

    Changes apply throughout the document

    Deletion of section 3.2 A Codes — Abort atApplication Interface
    Level following thedeimplementation of Application Interface in
    FIN

    Chapter 3, Alphanumeric Codes

    Deletion of section 3.17 U Codes — User Abort Codes Chapter 3,
    Alphanumeric Codes

    Preface

    22 July 2011 5

  • Chapter 1 IntroductionThe FIN error codes are divided into the
    following groups:

    Validation error codes

    Conditional semantic error codes

    Abort error codes

    All input messages are validated for syntax and semantic errors
    by the system. If there is an error, a validationerror code is
    returned in the logical (negative) acknowledgement or in an MT 019
    Abort Notification.

    Abort error codes give the reason why an application or the
    logical connection has been discontinued. Theyare generated
    following the recognition of a certain condition and not
    necessarily due to errors in a message.Abort error codes can come
    from the system or from a user’s terminal.

    For reference purposes, the error codes have been placed in two
    chapters. Chapter 2, Numeric Codes,contains all the errors that are
    represented by two- or three-digit codes. Error codes in Chapter
    3,Alphanumeric Codes, have the following format:

    where is a letter designating the error type and identifies the
    particular error.

    FIN

    6 Error Codes

  • Chapter 2 Numeric Codes

    2.1 GeneralNumeric codes are used for:

    Logout/Quit Acknowledgement errors (field 401)

    Re-Login Request errors (fields 280, 331 and 333)

    Retrieval errors (field 421)

    Message status (field 431)

    Abort reasons (field 432)

    FIN and General Purpose Application session termination (field
    443)

    Report errors (field 461)

    2.2 Logout/Quit Acknowledgement ErrorsThe following error codes
    are returned in field 401 of Logout and Quit acknowledgements.
    Logout and QuitCommands are always positively acknowledged and the
    session (General Purpose Application or FIN) closed.However, one of
    the following error codes can be included in the
    acknowledgement.

    01 Incorrect time/dayThe Logout Command can include the time/day
    inhibitor which prevents the next Loginoccurring before the
    time/day specified. The time/day in the format DDHHMM cannot be
    morethan 7 days after the current date.

    02 Training trailer missingThe trailer block is only present if
    the message is sent by a training logical terminal. If the
    LogoutCommand is sent from a training logical terminal, it must
    contain a Training trailer.

    03 Input sequence number errorEach message sent from a logical
    terminal has an input sequence number. The first messagesent in the
    General Purpose Application will always have an input sequence
    number of 000001,whereas the first message sent in FIN will have an
    input sequence number value of the lastinput sequence number+1 sent
    from that logical terminal. This error will be returned in
    theacknowledgement of a Logout or Quit Command when the input
    sequence number of thatcommand is incorrect.

    2.3 Re-Login Request ErrorsThe following error codes are
    returned in fields 280, 331, and 333 of acknowledgements, session
    historyreports, and daily check reports:

    010 Re-Login Request received while logical terminal is active
    on the Logical Terminal Controlassociation

    Chapter 2 Numeric Codes

    22 July 2011 7

  • 011 Logical Terminal Control state error, unable to recover the
    logical terminal session

    012 Re-Login Request authentication failed

    013 Re-Login Request semantic error

    014 Re-Login Request format error

    015 Re-Login Request login request number is incorrect

    016 Multiple Re-Logins from user

    017 Re-Login Request received while the logical terminal is in
    unrecoverable state

    019 Re-Login Request, session recovery information: incorrect
    General Purpose Application sessionnumber

    020 Re-Login Request, session recovery information: incorrect
    input sequence number

    021 Re-Login Request, session recovery information: input
    sequence number-ACK greater thaninput sequence number

    022 Re-Login Request, session recovery information: input
    sequence number-ACK less than thelower bound

    023 Re-Login Request, session recovery information: incorrect
    output sequence number

    024 Re-Login Request, session recovery information: incorrect
    window size

    026 Re-Login Request, login and re-login protocol versions are
    not the same

    027 Re-Login Request, logical terminal does not belong to Sign
    Distinguished Name (DN)organisation

    028 Re-Login Request, the Live destination that owns the Test
    and Training destination does notbelong to Sign Distinguished Name
    (DN) organisation

    2.4 Retrieval ErrorsThe following codes are returned in field
    421 of message retrievals:

    000 Message has no text block

    002 Message was encrypted and no key or the wrong key was
    supplied by the user

    FIN

    8 Error Codes

  • 003 Empty report (no messages found)

    004 Logical terminal is not authorised to retrieve the message,
    that is the requester is neither thesender nor the receiver of the
    original message

    005 Text lost due to Slice Processor recovery

    006 History lost due to Slice Processor recovery

    007 Target message is a retrieval report (MTs 021 or 023)

    010 Invalid MT received by Slice Processor pseudo logical
    terminal (system)

    011 Invalid received by Slice Processor pseudo logical terminal
    (system)

    012 Invalid date in retrieval criteria tag (system)

    013 Invalid time in retrieval criteria tag (system)

    014 End daytime before start daytime

    015 Target message older than 124 days (for range retrieval,
    daytime used)

    016 is not ‘XXX’

    018 Invalid destination for report (tag 102). The logical
    terminal must have the same destination asthe sender of the
    retrieval request or be a SWIFT logical terminal, and must be
    enabled for theapplication in which the retrieval message is to be
    sent

    019 Invalid input retrieval by receiver or output retrieval by
    sender (only single message inputreference/message output reference
    allowed)

    020 Invalid synonym retrieval (synonym is not sender or receiver
    of message)

    021 Unknown target logical terminal

    022 Request received at wrong Slice Processor (system)

    023 Could not retrieve message input reference in message output
    reference retrieval (system)

    032 No delivery attempt in message input reference retrieval by
    receiver

    033 On-line text read error (system)

    034 On-line history read error (system)

    Chapter 2 Numeric Codes

    22 July 2011 9

  • 035 Text read error from archival (system)

    036 History read error from archival (system)

    037 Partial report — major system recovery in progress

    038 Unable to retrieve text and history from archival because of
    system problems

    040 The limits for group retrieval (99 messages in one request)
    have been exceeded

    041 Message could not be decrypted (system)

    043 The logical terminals in the beginning message input
    reference/message output reference andthe ending message input
    reference/message output reference in a range retrieval request
    arenot the same, in tag 252 (message input reference range) or 254
    (message output referencerange)

    044 Illogical use of field 152 or field 153 . input sequence
    number or outputsequence number already included as component in
    message input reference(s) or messageoutput reference(s)

    045 Message text not retrievable (message not successfully
    delivered)

    046 Off-line retrieval not allowed for Test and Training
    messages

    047 The text of local test mode messages is not retrievable

    048 Retrieval message too long

    049 Retrieval period specified exceeds 10 days

    099 Retrieval report problem. Contact your Customer Support
    Centre

    2.5 Message StatusThe message status is returned in field 431 of
    non-delivery warnings, undelivered message reports, andretrieved
    messages.

    01 Delivered

    02 Rejected by destinee

    04 Aborted

    FIN

    10 Error Codes

  • 07 No delivery attempt

    08 One or more unsuccessful attempts

    10 Message not delivered (that is no delivery history) for one
    of the following reasons:

    Message negatively acknowledged on input

    Message is Login, Select, Quit or Logout Request

    Message was sent in local test mode (not deliverable)

    Message is MT 097 (processed directly by Slice Processor and
    never delivered to anylogical terminal, and so does not have a
    delivery history)

    12 Intercepted

    29 Message held for approval prior to Bypass mode and
    aborted

    31 Authorised by the copy service or Sanctions Screening over
    SWIFT service subscriber anddelivered

    32 Not authorised by the copy service or Sanctions Screening
    over SWIFT service subscriber andaborted by the system

    33 Copy message is aborted and not delivered to the copy
    service

    34 Authorised by the copy service or Sanctions Screening over
    SWIFT service subscriber butaborted by the system

    35 Not yet authorised/refused by the copy service or Sanctions
    Screening over SWIFT servicesubscriber

    37 Authorised by the copy service or Sanctions Screening over
    SWIFT service subscriber but nodelivery attempted

    38 Authorised by the copy service or Sanctions Screening over
    SWIFT service subscriber but oneor more unsuccessful delivery
    attempts

    41 Copy service bypassed and message delivered

    44 Copy service bypassed but message aborted by the system

    47 Copy service bypassed but no delivery attempted

    48 Copy service bypassed but one or more unsuccessful delivery
    attempts

    49 Refused by central institution. Abort notification MT 019
    contains an alphanumeric abort code

    Chapter 2 Numeric Codes

    22 July 2011 11

  • 50-99 These codes are specific to each FINCopy service. Contact
    your respective service provider forthe meaning of each code within
    the range 50-99.

    For Euro Banking Association (EBA) Processing, only the
    following codes are used:

    70 Refusal from the Clearing Computer, and delivery aborted; the
    Sender of thepayment message should also receive an MT 998 / SMT
    n75 Error Message fromthe Clearing Computer giving further reasons
    for the refusal.

    71 Refusal from the Clearing Computer because of a message
    format error thatprevented normal processing, and delivery
    aborted.

    99 System error

    2.6 Abort ReasonsThe following codes are returned in field 432
    of abort notifications and, for the FINCopy service,
    MessageRefusals:

    01 Message too old (remained undelivered for n days)

    02 Too many unsuccessful delivery attempts

    03 Destination disabled

    04 Operator aborted

    05 Message could not be recovered after a major system failure
    because it was user encrypted

    06 Message type incompatible with computer-based terminal
    mode

    11 Message is too old, but was authorised

    12 Too many delivery attempts, but message was authorised

    13 Destination is disabled, but message was authorised

    14 Message is too long, but was authorised

    21 Message is too old and was bypassed

    22 Too many delivery attempts and the message was bypassed

    23 Destination is disabled and the message was bypassed

    24 Message is too long and was bypassed

    FIN

    12 Error Codes

  • Note:

    29 Message held for approval prior to Bypass mode and
    aborted

    32 Message is too old and was not authorised

    33 Copy message to the copy service server was aborted

    35 FINCopy service parameter(s) incorrectly defined in FIN

    50-ZZ 99 is pre-defined as ‘system error’.All other alphanumeric
    codes (combination of 0-9 and A-Z) are specific to each
    FINCopyservice. Contact your respective service provider for the
    meaning of each code.

    Code S1 is used by the Sanctions screening service to indicate
    that the message has beenaborted on request of the subscribing
    user.

    All undefined numeric codes are reserved for use by FIN.

    2.7 FIN and General Purpose Application Session TerminationThe
    following codes are returned in field 443 of Service Message 14
    (for further details see the FIN SystemMessages):

    000 Normal termination

    001 Application Control or Logical Terminal Control has
    aborted

    002 Application Control or Logical Terminal Control has
    terminated normally

    004 System timed out message output reference ACK

    006 QUIT or LOGOUT received while outstanding input messages

    007 Input message/Service message after reception of a QUIT or
    LOGOUT

    008 Input window violation (more outstanding input messages than
    window size)

    009 System timed out on association establishment

    010 Reception of a SELECT from a logical terminal that already
    has a FIN session

    011 Association establishment request failed authentication

    014 Message output reference ACK Basic Header error

    015 Too many messages input in a session. Maximum is 500000.

    Chapter 2 Numeric Codes

    22 July 2011 13

  • 016 Too many messages output in a session. Maximum is
    500000.

    020 Message output reference ACK from wrong synonym

    025 As for 052 but due to receipt of a Re-Login Request, rather
    than a Login Request

    051 As for 052 but on a different Regional Processor

    052 Reception of a login from a logical terminal for which the
    system has already processed a logintransmitted over a different
    Logical Terminal Control on the same Regional Processor.
    Theexisting session is aborted and the new session established.

    053 SELECT with bad text block

    054 AP ABORT REQUEST with bad text block

    2.8 Report ErrorsThe following codes are returned in field 461
    of Delivery Subset Status Reports, Undelivered MessageReports, and
    Undelivered SSI Update Notification Reports:

    001 Empty report

    002 End of undelivered report

    003 System undergoing major recovery or system not completely
    synchronised yet

    004 Too many undelivered messages

    005 User on fall back Regional Processor, cannot generate
    report

    006 The message referenced in the request could not be
    found.

    007 Invalid destination for report. The sender of the request
    must be the same as the sender of themessage referenced in the
    request.

    008 No MTs 671 were found for the referenced MT 670.

    009 Requesting logical terminal in invalid state

    016 Branch code is not «XXX’

    099 System internal problems, contact your Customer Support
    Centre

    FIN

    14 Error Codes

  • 2.9 Bulk Retrieval Errors CodesThe following codes are returned
    in field 144 of Bulk Retrieval Responses (MT 025):

    03 Retrieval only partially complete

    11 Invalid

    12 Invalid

    13 Invalid retrieval time range

    14 Retrieval aborted due to system error

    15 Retrieval aborted due to communication error

    16 Retrieval aborted by SWIFT

    19 Retrieval completeThe text of messages that were sent to the
    retrieving BIC more than 124 days ago cannot beretrieved. If those
    messages were received by the retrieving BIC less than 124 days
    ago, the filecontains the message output reference of the history
    and the message input reference of thetext.

    20 Retrieval aborted due to system error (Test and Training
    destination — attempt to use tape)

    21 Retrieval aborted due to system error (FIN/FIN Bridge key
    error)

    22 Retrieval aborted due to system error (missing master
    BIC)

    Chapter 2 Numeric Codes

    22 July 2011 15

  • Note:

    Note:

    Chapter 3 Alphanumeric Codes

    3.1 GeneralThis chapter contains the codes for the following
    error types:

    Code Error Type Code Error Type

    A Abort at Application Interface Level Errors R
    Re-login/Re-select Errors

    A Re-select Errors S System-initiated Abort Errors

    B Copy Service Errors S Select Errors

    C Dialout Errors T Text validation (Block 4) Errors

    C, Dand E

    Conditional Semantic Errors U User Header Validation Errors

    G Service-specific Validation Errors U User Abort Errors

    H Basic Header and Application HeaderValidation Errors

    V System Message or Message BlockFormat Errors

    K Code Words Errors in Generic Fields X Delayed NAK Errors and
    FINCopyService Message Refusals

    L LOGIN Errors Y User Negative Acknowledgement Errors

    M Message Errors Z Trailer Validation Errors

    P Protocol Errors

    Similar error codes are used by other SWIFT services, such as
    Accord, or Processing forEuro Banking Association (EBA), and can
    have different meanings. The error codes used byeach of the
    services are described in the respective service documentation.

    3.2 A Codes — Re-select Error CodesA56 Re-select NAK error code
    (in field tag 503) to indicate that the logical terminal is not in
    a

    recoverable state. The computer-based terminal should execute a
    fresh select procedure.

    3.3 B Codes — Copy Service ErrorsSimilar error codes are used by
    other SWIFT services, such as Accord, or Processing for

    Euro Banking Association (EBA), and can have different meanings.
    The error codes used byeach of the services are described in the
    respective service documentation.

    B01 Message contains Value-Added Service server id but sender or
    receiver, or both, are notmembers of the service.

    B02 Available.

    FIN

    16 Error Codes

  • B03 103:TPS is present in the message but the sender is not a
    member of TPS, or the message isnot allowed for TPS.

    B04 Available.

    B05 Either a system error has occurred, in which case, the user
    should contact its local CustomerSupport Centre for further
    information or it was not possible to generate a copy message
    asnone of the fields to be copied were present in the original
    message.

    3.4 C, D, and E Codes — Conditional Semantic Error CodesNote

    Where a natural language expression would be too difficult to
    synthesise or too long, amatrix is provided. The row and column
    headers identify the elements involved (forexample, field tags,
    code words, letter options). Matrices should be read from left
    toright and from top to bottom. The following abbreviations are
    used:

    M = Mandatory (must be present)

    O = Optional (may be present)

    U = Unauthorised (must not be present)

    Y = Yes (is present)

    N = No (is not present)

    NA = Not applicable

    3.4.1 C Error Codes

    C00 Not used.

    C01 MTs 102, 102+, 104, and 107If field 19 is present in
    sequence C, then it must equal the sum of the amounts in all
    occurrencesof field 32B in sequence B.

    MTs 201, 203, 204, and 559The amount in field 19 must equal the
    sum of the amounts in all occurrences of field 32B or 34A.

    MT 256If field 19 is present in sequence C, then it must equal
    the sum of the amounts in all occurrencesof field 32J in sequence
    B.

    MT 824Field 19 at the completion of each outer repetitive
    sequence must equal the sum of the productsof subfields 1 and 3 in
    all occurrences of field 68A from its respective inner
    repetitivesequence(s).

    Chapter 3 Alphanumeric Codes

    22 July 2011 17

  • C02 The currency code must be the same for all occurrences of
    indicated fields in the entiremessage. See the SWIFT Standards
    Category volumes for the indicated fields in eachmessage.

    Examples:

    The following list explains how Error code C02 is applied in
    specific message types:

    MT 321. The currency code in the amount fields (fields 19A in
    sequence B) must be thesame for all occurrences of this field in
    the message.

    MTs 320 and 330. The currency code in the amount fields, except
    for fields 33B and 33E insequence G, must be the same for all
    occurrences of these fields in the message.

    MT 350. The currency code in the amount fields 32B and 34B in
    sequence B must be thesame.

    Special Cases:

    The following MTs apply Error code C02 in an exceptional manner
    (for example, either based onthe presence of another field OR
    individually to separate groups of fields within the MT):

    MTs 103 and 103+. If field 71G is present, the currency code in
    the fields 71G and 32Amust be the same.

    MTs 104 and 107. The currency code in fields 32B and 71 G in
    sequences B and C must bethe same for all occurrences of these
    fields in the message. The currency code in field 71Fin sequences B
    and C must be the same for all occurrences of this field in the
    message.

    MT 320. The currency codes in the amount fields 32B, 32H, and
    34E in sequence B, andfield 71F in sequence H, must be the
    same.

    MT 620. If field 32H is present, then the currency code must be
    the same as the currencycode in field 32B.

    C03 The number of decimal digits in the amount component is
    checked against the maximumallowed for the corresponding currency.
    This check is mostly applied to fields containing boththe amount
    and the currency code components.

    Examples:

    field 32A in MT 103, and in MT 256, sequence C

    field 32B in MTs 104 and 107, sequences B and C

    This check also applies, among others, to:

    field 19 in MTs 102, 104, 107, 201, 203, 204, and 559 where the
    corresponding currency isthe one used in field 32B or 34A

    field 19 in MT 824 where the corresponding currency is the one
    used in correspondingoccurrences of field 68A

    field 32J in sequence B, and to field 19 in sequence C, in MT
    256 where the correspondingcurrency is the one used in field
    32A

    field 33B in MT 103, and in MTs 104 and 107, sequence B

    field 71F in MT 103, and in MTs 104 and 107, sequences B and
    C

    field 71G in MT 103, and in MTs 104 and 107, sequences B and
    C

    field 72 Reject/Return in MT 103, and in MTs 104 and 107,
    sequence A

    FIN

    18 Error Codes

  • Note:

    Note:

    Error code C03 should be applied only to field 68A in MT 824 if
    subfield 5 ispresent.

    C04 MTs 503, 504, and 506In sequence B, if field :19B::TEXA is
    not present, then field :19B::TCRL is mandatory; otherwisefield
    :19B::TCRL is optional.

    Sequence B

    If field :19B::TEXA is … Then field :19B::TCRL is …

    Not present Mandatory

    Present Optional

    C05 Identifier Code must be a financial institution BIC. This
    error code applies to all types of BICsreferenced in a FIN message,
    including SWIFT BICs, Non-SWIFT BICs, Masters, Synonyms,Live
    destinations and Test & Training destinations.

    See the table below for the list of MTs affected.

    MT Field Sequence(s) Qualifier Comments

    52A A, B

    56A B

    101

    57A B

    52A A, B

    53A C

    54A C

    102

    57A B

    The same validation applies to thegeneric MT 102 without tag
    119,and the MT 102+

    52A

    53A

    54A

    55A

    56A

    103

    57A

    The same validation applies to thegeneric MT 103 without tag
    119,and other variants, such as the MT103 REMIT and the MT 103+

    52A A, B

    53A C

    104

    57A B

    The same validation applies to thegeneric MT 104 without tag
    119,and the MT 104 RFDD

    For sequence C, seeError code C96.

    52A A, B

    53A C

    107

    57A B

    Chapter 3 Alphanumeric Codes

    22 July 2011 19

  • MT Field Sequence(s) Qualifier Comments

    52A

    53A

    110

    54A

    111,112

    52A

    56A200,201

    57A

    52A

    53A

    54A

    56A

    57A

    202,203

    58A

    52A A

    53A A

    54A A

    56A A

    57A A

    58A A

    52A B

    56A B

    202COV

    57A B

    53A B

    57A A

    204

    58A A

    52A

    53A

    56A

    57A

    205

    58A

    FIN

    20 Error Codes

  • MT Field Sequence(s) Qualifier Comments

    52A A

    53A A

    56A A

    57A A

    58A A

    52A B

    56A B

    205COV

    57A B

    51A A

    52A A

    52G A

    56A B

    57A B

    207

    58A B

    52A210

    56A

    256 57A C

    53AJ B1, B2, D

    56AJ B1, B2, D

    300

    57AJ B1, B2, D

    53AJ D1, D2, D3

    56AJ D1, D2, D3

    303

    57AJ D1, D2, D3

    53AJ B, E

    56AJ B, E

    304

    57AJ B, E

    53A

    56A

    305

    57A

    Chapter 3 Alphanumeric Codes

    22 July 2011 21

  • MT Field Sequence(s) Qualifier Comments

    53AJ C, E, J

    56AJ C, E, J

    57AJ C, E, J

    84AJ B

    306

    86AJ C, E, J

    95P B3a CDEA INTE ACCW307

    95P D1 CDEA INTE ACCW

    53AJ C, D, E, F, I

    56AJ C, D, E, F, I

    57AJ C, D, E, F, I

    320

    86AJ C, D, E, F, I

    321 95P C1 CDEA INT2 INTEACCW

    53AJ C, D, E, F

    56AJ C, D, E, F

    57AJ C, D, E, F

    330

    86AJ C, D, E, F

    53AJ C, D, F

    56AJ C, D, F

    57AJ C, D, F

    340

    86AJ C, D, F

    53AJ C

    56AJ C

    57AJ C

    341,350

    86AJ C

    53A D, G, L, M

    56A D, G, L, M

    57A D, G, L, M

    360

    86A D, G, L, M

    FIN

    22 Error Codes

  • MT Field Sequence(s) Qualifier Comments

    53A D, G, J, K, L,M

    56A D, G, J, K, L,M

    57A D, G, J, K, L,M

    361

    86A D, G, J, K, L,M

    53A C, E

    56A C, E

    57A C, E

    362

    86A C, E

    53A L, M

    56A L, M

    57A L, M

    364

    86A L, M

    53A J, K, L, M

    56A J, K, L, M

    57A J, K, L, M

    365

    86A J, K, L, M

    52A

    53A

    54A

    57A

    400

    58A

    416 53A A

    450,455,456

    52A

    502 95P C2 ACCW PAYE

    504 95P C2a1, E1 ACCW PAYE

    505 95P B2a1, D1 ACCW PAYE

    507 95P B1b1 ACCW PAYE

    513 95P D2 ACCW PAYE

    514 95P C2 ACCW PAYE

    Chapter 3 Alphanumeric Codes

    22 July 2011 23

  • MT Field Sequence(s) Qualifier Comments

    515 95P D2 ACCW PAYE

    516 57A B

    518 95P C2 ACCW PAYE

    540,541,542,543,544,545,546,547

    95P E2 ACCW PAYE

    559 57A

    566 95P D2a ACCW

    578 95P E2 ACCW PAYE

    53A B

    56A B, C

    57A B, C

    86A B, C

    600

    87A B, C

    53A

    56A

    601

    57A

    56A

    86A

    604

    87A

    86A605

    87A

    606 87A

    607 87A

    53AJ C, D, E, F

    56AJ C, D, E, F

    57AJ C, D, E, F

    620

    86AJ C, D, E, F

    643 57A B, C

    644 57A B

    646 57A C

    FIN

    24 Error Codes

  • MT Field Sequence(s) Qualifier Comments

    670 95P B1 ACCW INT1 INT2

    41A

    42A

    51A

    53A

    700

    57A

    41A705

    57A

    707 52A

    41A

    42A

    51A

    52A

    53A

    710

    57A

    41A

    42A

    52A

    720

    57A

    730,734

    57A

    41A

    42A

    740

    58A

    52A

    57A

    742

    58A

    750 57A

    53A752

    54A

    53A

    57A

    754

    58A

    Chapter 3 Alphanumeric Codes

    22 July 2011 25

  • MT Field Sequence(s) Qualifier Comments

    53A756

    54A

    768,769

    57A

    51A

    52A

    53A

    800

    54A

    801 51A

    52A

    53A

    802

    54A

    824 51A

    900 52A

    52A910

    56A

    985 57A

    n90 52A

    52An91

    57A

    C06 MT 210Either field 50a or field 52a, but not both, must be
    present in a repetitive sequence.

    MTs 710 and 720Either field 52a or field 50B, but not both, must
    be present.

    If field 52a is … Then field 50B is …

    Present Not allowed

    Not present Mandatory

    MT 910Either field 50a or field 52a, but not both, must be
    present.

    C07 MT 516Either field 35A or 35N must be present.

    C08 Available.

    FIN

    26 Error Codes

  • C09 MT 430In each occurrence of sequence A, if field 33a is
    present, then field 32a must be present.

    C10 MT 422At least one of the fields 72, 75 or 76 must be
    present.

    C11 MT 400If field 57a is present, fields 53a and 54a must be
    present.

    C12 MTs 707 and 747When field 32B or 33B is present, field 34B
    must be present. Conversely, when field 34B ispresent, either field
    32B or field 33B must be present.

    C13 MT 750If any of fields 33B, 71B or 73 is present, field 34B
    must be present.

    C14 MTs 559 and 754Either field 53a or 57a, but not both, may be
    present.

    C15 MT 747At least one of the fields 31E, 32B, 33B, 34B, 39A,
    39B, 39C, 72 or 77A must be present.

    C16 MT 707If field 23 is present, field 52a must be present.

    C17 MT 734If field 73 is present, field 33a must be present.

    C18 MT 752If fields 32B and 71B are present, field 33a must be
    present.

    C19 MT 754Either field 72 or field 77A, but not both, may be
    present.

    C20 MT 601Field 53a may be present only if field 34P is
    present.

    C21 MT 506If sequence C is not present, then sequence D is
    mandatory. If one or more occurrence ofsequence C is/are present,
    then sequence D is optional.

    If sequence C is … Then sequence D is …

    Not present Mandatory

    Chapter 3 Alphanumeric Codes

    22 July 2011 27

  • Note:

    If sequence C is … Then sequence D is …

    Present (once or more) Optional

    C22 MT 920If field 12 contains 942, field 34F must be present in
    the same repetitive sequence.

    C23 MTs 920 and 942When only one field 34F is present, subfield
    2 must not be used. When both fields 34F arepresent, subfield 2 of
    the first 34F must contain D, and subfield 2 of the second 34F
    mustcontain C.

    In MT 920, this applies to each repetitive sequence.

    C24 MT 940If field 86 is present in any occurrence of the
    repetitive sequence, it must be preceded by a field61.

    C25 MT n92Field 79 or a copy of at least any fields of the
    original message or both must be present.

    If field 79 is … Then copy of any field(s) of originalmessage
    is …

    Present Optional

    Not present Mandatory (that is, minimum one field, anyfield)

    SWIFT does not validate the relationship between the copied
    fields and theoriginal message, hence, any valid field is correct.
    The system will negativelyacknowledge the MT n92 with Error code
    C25 if there is no more field after field11S.

    C26 MT 430At least one of the optional fields 32a or 74 must be
    present.

    C27 MTs 940, 941, 942, 950, 970, and 972The first two characters
    of the three-character currency code in fields 60F, 60M, 62F, 62M,
    64,65, 90C and 90D, in MTs 940, 941, 942, 950, 970 and 972, and
    field 34F in MT 942 must be thesame for all occurrences of these
    fields.

    C28 MT 541, 543, 578A value date must only be provided for
    cash/securities split settlement. That is, in anyoccurrence of
    subsequence E3, if value date field :98a::VALU is present, then in
    sequence Efield :22F::STCO//SPST must be present, and settlement
    amount field :19A::SETT must bepresent in the same subsequence
    E3.

    FIN

    28 Error Codes

  • Note:

    Note:

    In any occurrence ofsubsequence E3

    if field :98a::VALU is …

    Sequence Ethen field

    :22F::STCO//SPST (withDSS not present)

    In the same occurrence ofsubsequence E3

    and field :19A::SETT is …

    Present Mandatory Mandatory

    Not present Optional Optional

    MT 544, 545, 546, 547A value date must only be provided with an
    effective settlement amount, that is, in anyoccurrence of
    subsequence E3, if value date field :98a::VALU is present, then
    settled amountfield :19A::ESTT must be present in the same
    subsequence.

    Subsequence E3if field :98a::VALU is …

    Subsequence E3then field :19A::ESTT is …

    Present Mandatory

    Not present Optional

    MTs 544, 545, 546, and 547, see Network Validated Rule 287
    (Error codeE87).

    MTs 545 and 547, see Network Validated Rule 292 (Error code
    E92).MT 586A value date must only be provided for cash/securities
    split settlement. That is, in anyoccurrence of subsequence B5b, if
    value date field :98a::VALU is present, then in subsequenceB5 field
    :22F::STCO//SPST must be present, and settlement amount field
    :19A::SETT must bepresent in the same subsequence B5b.

    In any occurrence ofsubsequence B5b

    if field :98a::VALU is …

    Subsequence B5then field

    :22F::STCO//SPST (withDSS not present) is …

    In the same occurrence ofsubsequence B5b

    and field :19A::SETT is …

    Present Mandatory Mandatory

    Not present Optional Optional

    C29 Available.

    C30 MT 707At least one of the fields 31E, 32B, 33B, 34B, 39A,
    39B, 39C, 44A, 44E, 44F, 44B, 44C, 44D, 79or 72 must be
    present.

    C31 MTs n95 and n96Either field 79 or a ‘copy of any field(s) of
    the original message to which this message relates’,but not both,
    may be present.

    SWIFT does not validate the relationship between the copied
    fields and theoriginal message; hence any valid fields other than
    79 are accepted.

    Chapter 3 Alphanumeric Codes

    22 July 2011 29

  • C32 MTs 300, 303, 304, 306, 320, 330, 340, 350, 360, 361, 362,
    364, 365, 600, 620, and 643An optional sequence of fields was used.
    However, a field that is required (that is, indicated byan ‘OR’) or
    a field that is mandatory (that is, indicated by ‘Mandatory in
    …’) within this sequenceis missing.

    C33 MTs 768 and 769If field 71B is present, field 32a must be
    present.

    C34 MT 769Either field 33B or 39C, but not both, must be
    present.

    C35 MTs 643, 644, 646, and 649Either field 21 or 29B must be
    present.

    C36 MTs 643 and 646Subfield 2 () of field 31F must be present in
    each occurrence of sequence B.

    C37 MT 577Subfield 2 () of field 67A must not be present.

    C38 Available.

    C39 Available.

    C40 MT 920The currency code must be the same for each occurrence
    of the indicated fields within eachrepetitive sequence.

    C41 Available.

    C42 MT 824The currency code in each of the fields 68A of a
    sequence of fields 68A preceding a field 19must be the same.

    C43 MT 646Either field 32N or 33N must be present.

    C44 MT 646If fields 32N and 33N are present in sequence C, field
    34a must be present in sequence C.

    C45 MT 646If field 23 contains REPRINC or PREPRINC, field 32N
    must be present in sequence C.

    FIN

    30 Error Codes

  • C46 MT 646If field 23 contains INT, field 33N must be present in
    sequence C.

    C47 MT 643If field 23 contains LOAN/DRAWDOWN or FINARR/DRAWDOWN,
    sequence B must not bepresent.

    C48 MT 643If field 23 contains LOAN/RENEWAL or FINARR/RENEWAL,
    sequence B must be present.

    C49 MT 456If field 71B is present, the values in fields 32a and
    33D must be different.

    C50 MTs 540, 541, 542, and 543If field 36B is present in minimum
    one occurrence of sequence A1, then the type of
    settlementtransaction must be a pair-off or a turn-around, that is,
    sequence E field :22F::SETR//PAIR or:22F::SETR//TURN must be
    present.

    In sequence A1if field :36B: is …

    Then in sequence Efield :22F::SETR must be …

    Present :22F::SETR//PAIR and DSS must not
    bepresentor:22F::SETR//TURN and DSS must not bepresent

    Not present NA

    C51 MT 643If field 23 contains LOAN/DRAWDOWN or LOAN/RENEWAL,
    field 31R must be present.

    C52 Available.

    C53 MT 643If field 71C is present in any sequence B, field 34a
    must be present in the same sequence.

    C54 MT 644Either field 36 or field 37(A-F) must be present in
    any sequence B.

    C55 MT 644In any sequence B, the currency code in fields 33B and
    34a must be the same.

    C56 Available.

    Chapter 3 Alphanumeric Codes

    22 July 2011 31

  • C57 MT 646If field 34N is present in any sequence B, field 31F
    in the same sequence B and field 33N insequence C must be
    present.

    C58 MT 300In field 77D of sequence A, if the code /VALD/ is
    present, then it must appear in the first 6characters of the first
    line and in no other place, and it must be followed by a date
    expressed asYYYYMMDD and the «end_of_line» separator, that is,
    «:77D:/VALD/»YYYMMDD»CrLf».

    See rule 59.

    MT 304In field 72 of sequence C, if the code /VALD/ is present,
    then it must appear in the first 6characters of the first line and
    in no other place, and it must be followed by a date expressed
    asYYYYMMDD and the «end_of_line» separator, that is
    «:72:/VALD/»YYYMMDD»CrLf».

    See rule 59.

    MT 646If field 34N is present in any sequence B, the total
    amount given in field 33N must equal the totalamount of all
    occurrences of field 34N amounts in sequence B.

    C59 MT 300In sequence A, if field 77D is present and if the
    first six (6) characters of the first line are equal to/VALD/, then
    the second line must be present and it must contain «/SETC/» in the
    first 6characters, followed by a valid ISO 4217 currency code and
    the end of line separator, that is,»/SETC/»»CrLf».

    Conversely, in sequence A, if field 77D is present, and the
    second line is present, and the firstsix (6) characters of the
    second line are equal to /SETC/, then the first six (6) characters
    of thefirst line must be equal to /VALD/.

    The code «/SETC/» is not allowed in other places than the first
    6 characters of the second line.

    See rule 58.

    MT 304In sequence C, if field 72 is present, and the first six
    (6) characters of the second line are equalto /SETC/, then the
    first six (6) characters of the first line must be equal to /VALD/
    and /SETC/must be followed by a valid ISO 4217 currency code and
    the end of line separator, that is,»/SETC/»»CrLf».

    The code «/SETC/» is not allowed in other places than the first
    6 characters of the second line.

    See rule 58.

    MT 321In sequence B, the presence of field 19A and of the Next
    Interest Due Date (field :98A::INTR)depends on the Type of
    Loan/Deposit Event (field :22H::TLDE) in sequence A as follows:

    In sequenceA

    if field:22H::TLDE

    Indicatoris …

    Sequence Bthen field

    :98A::INTRis …

    Sequence Band field

    :19A::SETTis …

    Sequence Band field

    :19A::RODIis …

    Sequence Band field

    :19A::CINTis …

    SequenceB

    and field:19A::NINT

    is …

    CONF Mandatory Not allowed Not allowed Not allowed Mandatory

    ROLL Mandatory Mandatory Optional Optional Mandatory

    FIN

    32 Error Codes

  • In sequenceA

    if field:22H::TLDE

    Indicatoris …

    Sequence Bthen field

    :98A::INTRis …

    Sequence Band field

    :19A::SETTis …

    Sequence Band field

    :19A::RODIis …

    Sequence Band field

    :19A::CINTis …

    SequenceB

    and field:19A::NINT

    is …

    MATU Not allowed Mandatory Not allowed Optional Not allowed

    MT 800The amounts in fields 34B and 32A must be the same.

    C60 MT 307In sequence A, the presence of field :22H::APER and
    the presence of field :22H::NEGR dependon the field :22H::CRTR as
    follows:

    In sequence Aif field :22H::CRTR Indicator

    is …

    Sequence Athen field :22H::APER is …

    Sequence Aand field :22H::NEGR is …

    ASET Not allowed Optional

    AFWD Mandatory Mandatory

    MT 321In sequence A, the presence of field :99B:: depends on the
    presence of field :22H::BLOC asfollows:

    In sequence Aif field :22H::BLOC is …

    Sequence Athen field :99B:: is …

    Present Mandatory

    Not present Not allowed

    MT 643In each sequence B, the currency code in fields 32P, 33a
    and 34a must be the same.

    C61 MT 307In sequence A, the presence of field :22H::PAFI
    depends on field :22H::APER as follows:

    In sequence Aif field :22H::APER

    Indicator is …

    Sequence Athen field :22H::PAFI is …

    OPEF Not allowed

    NOPE Mandatory

    Field :22H::APER not present Not allowed

    MT 321In sequence B, the presence of field :98A::LDFP depends on
    the value of field :22H::TLDE asfollows:

    Chapter 3 Alphanumeric Codes

    22 July 2011 33

  • In sequence Aif field :22H::TLDE

    Indicator is …

    Sequence Bthen field :98A::LDFP

    is …

    MATU Not allowed

    Not MATU Optional

    MT 643In each sequence C, the currency code in fields 32B and
    33B must be the same.

    C62 MT 307The presence of sequence C depends on field :22H::APER
    as follows:

    In sequence Aif field :22H::APER

    Indicator is …

    Thensequence C

    is …

    OPEF Not allowed

    NOPE Mandatory

    Field :22H::APER not present Not allowed

    MT 321In sequence B, the presence of field :99B::DAAC depends on
    the presence of field :98A::LDFPas follows:

    In sequence Bif field :98A::LDFP

    is …

    Sequence Bthen field :99B::DAAC

    is …

    Present Mandatory

    Not present Not allowed

    C63 MT 307In sequence A, the presence of the qualifier UNKN in
    field :22H::NEGR//UNKN depends on thecontent of field :22H::CRTR,
    of field :22H::APER and of field :22H::PAFI as follows:

    In sequence Aif field :22H::

    is …

    Then field:22H::NEGR//UNKN

    is …

    CRTR//ASET Not allowed

    CRTR//AFWD and APER//OPEF Optional

    CRTR//AFWD and APER//NOPE andPAFI//PAIN

    Optional

    CRTR//AFWD and APER//NOPE andPAFI//FINA

    Not allowed

    MT 321In sequence A, if field 99B is present, then all
    qualifiers must be present.

    FIN

    34 Error Codes

  • C64 MT 307The presence of sequence D depends on the value of
    field 22H as follows:

    In sequence A

    If field:22H::CRTR

    is …

    And field:22H::APER

    is …

    And field:22H::PAFI

    is …

    And field:22H::NEGR

    is …

    Thensequence D

    is …

    ASET NA per rule 60 NA per rule 61 NETC Optional

    ASET NA per rule 60 NA per rule 61 GRSC Not allowed

    ASET NA per rule 60 NA per rule 61 Not present Not allowed

    AFWD OPEF NA per rule 61 NETC or GRSCor UNKN

    Not allowed

    AFWD NOPE PAIN NETC or GRSCor UNKN

    Not allowed

    AFWD NOPE FINA NETC Mandatory

    AFWD NOPE FINA GRSC Not allowed

    C65 MT 567If the message is a cancellation request status
    (:23G::CAST), then, in every occurrence ofsequence A2 Status, a
    cancellation processing status must be reported
    (:25D::CPRC…).

    If the message is an instruction status (:23G::INST) then, in
    every occurrence of sequence A2Status, an instruction processing
    status (:25D::IPRC…) must be reported.

    If the message is corporate action event processing status
    (:23G::EVST), then, in everyoccurrence of sequence A2 Status, an
    event status (:25D::EPRC…) must be reported.

    In sequence Aif field 23G is …

    Then, in every occurrence of sequence A2Status,

    field :25D must be …

    CAST :25D::CPRC…

    INST :25D::IPRC…

    EVST :25D::EPRC…

    C66 MT 643The number of occurrences of sequence C must be equal
    to or greater than the number ofoccurrences of sequence B.

    C67 MT 516In sequence A, either field 83C or 87a but not both,
    may be present.

    C68 MTs 202 COV and 205 COVIn sequence B, if field 56a is
    present, then field 57a must also be present.

    Chapter 3 Alphanumeric Codes

    22 July 2011 35

  • Note:

    C69 MT 507In each occurrence of sequence B, if present, if
    subsequence B1 is present, the presence ofsubsequences B1a and B1b
    depends on the value of field :22H::COLL in sequence B
    asfollows:

    In each occurrence of sequence B

    If subsequence B1is …

    And in sequence Bfield

    :22H::COLL//Statusis …

    Then subsequenceB1a is …

    And subsequenceB1b is …

    CCOL Not allowed Mandatory

    SCOL Mandatory Not allowed

    Present

    BCOL(NA see Error code

    C70)

    NA NA

    Not present NA NA NA

    Rule C70 takes precedence over rule C69.

    C70 MT 507In each occurrence of sequence B, the presence of
    subsequence B1 depends on the value offields :25D::COLL// and
    :22H::COLL// as follows:

    In each occurrence of sequence B

    If field :25D::COLL/[8c]/4!c Data Source

    Scheme [8c] is …

    And field:25D::COLL/[8c]/4!c

    is …

    And field:22H::COLL//4!c is …

    Then subsequenceB1 is …

    :25D::COLL//ACCT BCOL Not allowed

    :25D::COLL//ACCT CCOL Mandatory [1]

    :25D::COLL//ACCT SCOL Mandatory [1]

    Not present

    :25D::COLL//REJT NA Not allowed

    BCOL Not allowed

    CCOL Optional [1]

    Present NA

    SCOL Optional [1]

    [1] See Error code C69 for additional checks. Rule C70 takes
    precedence over rule C69.

    C71 MT 535In each occurrence of subsequence B1, field 93B::AGGR
    cannot appear more than twice(maximum 2 occurrences). When
    repeated, one occurrence must have Quantity Type CodeFAMT and the
    other occurrence must have Quantity Type Code AMOR.

    FIN

    36 Error Codes

  • Subsequence B1if field :93B::AGGR is …

    Then one occurrence of:93B:AGGR must be …

    And the other occurrenceof :93B::AGGR must be …

    Repeated :93B::AGGR//FAMT and DSSmust not be present

    :93B::AGGR//AMOR andDSS must not be present

    Not repeated NA NA

    MT 536In each occurrence of subsequence B1a2, field 36B::PSTA
    cannot appear more than twice(maximum 2 occurrences). When
    repeated, one occurrence must have Quantity Type CodeFAMT and the
    other occurrence must have Quantity Type Code AMOR.

    Subsequence B1a2if field :36B::PSTA is …

    Then one occurrence of:36B::PSTA must be …

    And the other occurrenceof :36B::PSTA must be …

    Repeated :36B::PSTA//FAMT :36B::PSTA//AMOR

    Not repeated NA NA

    MT 537In each occurrence of subsequence B2b, field 36B::PSTA
    cannot appear more than twice(maximum 2 occurrences). When
    repeated, one occurrence must have Quantity Type CodeFAMT and the
    other occurrence must have Quantity Type Code AMOR.

    Subsequence B2bif field :36B::PSTA is …

    Then one occurrence of:36B::PSTA must be …

    And the other occurrenceof :36B::PSTA must be …

    Repeated :36B::PSTA//FAMT :36B::PSTA//AMOR

    Not repeated NA NA

    MTs 540, 541, 542, and 543In sequence C, field 36B::SETT cannot
    appear more than twice (maximum 2 occurrences).When repeated, one
    occurrence must have Quantity Type Code FAMT and the
    otheroccurrence must have Quantity Type Code AMOR.

    Sequence Cif field :36B::SETT is …

    Then one occurrence of:36B::SETT must be …

    And the other occurrenceof :36B::SETT must be …

    Repeated :36B::SETT//FAMT :36B::SETT//AMOR

    Not repeated NA NA

    MTs 544, 545, 546, and 547In sequence C, field 36B::ESTT cannot
    appear more than twice (maximum 2 occurrences).When repeated, one
    occurrence must have Quantity Type Code FAMT and the
    otheroccurrence must have Quantity Type Code AMOR.

    Sequence Cif field :36B::SETT is …

    Then one occurrence of:36B::ESTT must be …

    And the other occurrenceof :36B::ESTT must be …

    Repeated :36B::ESTT//FAMT :36B::ESTT//AMOR

    Not repeated NA NA

    MT 548In sequence. B, field 36B::SETT cannot appear more than
    twice (maximum 2 occurrences).When repeated, one occurrence must
    have Quantity Type Code FAMT and the otheroccurrence must have
    Quantity Type Code AMOR.

    Chapter 3 Alphanumeric Codes

    22 July 2011 37

  • Sequence Bif field :36B::SETT is …

    Then one occurrence of:36B::SETT must be …

    And the other occurrenceof :36B::SETT must be …

    Repeated :36B::SETT//FAMT :36B::SETT//AMOR

    Not repeated NA NA

    MT 564In each occurrence of subsequence B2, field 93B::ELIG
    cannot appear more than twice(maximum 2 occurrences). When
    repeated, one occurrence must have Quantity Type CodeFAMT and the
    other occurrence must have Quantity Type Code AMOR.

    Subsequence B2if field :93B::ELIG is …

    Then one occurrence of:93B:ELIG must be …

    And the other occurrenceof :93B::ELIG must be …

    Repeated :93B::ELIG//FAMT and DSSmust not be present

    :93B::ELIG//AMOR and DSSmust not be present

    Not repeated NA NA

    MT 565In subsequence B2, field 93B::ELIG cannot appear more than
    twice (maximum 2 occurrences).When repeated, one occurrence must
    have Quantity Type Code FAMT and the otheroccurrence must have
    Quantity Type Code AMOR.

    Subsequence B2if field :93B::ELIG is …

    Then one occurrence of:93B::ELIG must be …

    And the other occurrenceof :93B::ELIG must be …

    Repeated :93B::ELIG//FAMT and DSSmust not be present

    :93B::ELIG//AMOR and DSSmust not be present

    Not repeated NA NA

    MT 566In sequence B, field 93B::ELIG cannot appear more than
    twice (maximum 2 occurrences).When repeated, one occurrence must
    have Quantity Type Code FAMT and the otheroccurrence must have
    Quantity Type Code AMOR.

    Sequence Bif field :93B::ELIG is …

    Then one occurrence of:93B:ELIG must be …

    And the other occurrenceof :93B::ELIG must be …

    Repeated :93B::ELIG//FAMT and DSSmust not be present

    :93B::ELIG//AMOR and DSSmust not be present

    Not repeated NA NA

    MT 567In sequence B, field 36B::STAQ or QREC cannot appear more
    than twice (maximum 2occurrences). When repeated, one occurrence
    must have Quantity Type Code FAMT and theother occurrence must have
    Quantity Type Code AMOR.

    Sequence Bif field :36B::STAQ or QREC

    is …

    Then one occurrence of:36B:STAQ or QREC must

    be …

    And the other occurrenceof :36B::STAQ or QRECmust be …

    :36B::STAQ//FAMT or :36B::STAQ//AMORRepeated

    :36B::QREC//FAMT :36B::QREC//AMOR

    Not repeated NA NA

    FIN

    38 Error Codes

  • MT 568In sequence B, field 93B::ELIG cannot appear more than
    twice (maximum 2 occurrences).When repeated, one occurrence must
    have Quantity Type Code FAMT and the otheroccurrence must have
    Quantity Type Code AMOR.

    Sequence Bif field :93B::ELIG is …

    Then one occurrence of:93B:ELIG must be …

    And the other occurrenceof :93B::ELIG must be …

    Repeated :93B::ELIG//FAMT and DSSmust not be present

    :93B::ELIG//AMOR and DSSmust not be present

    Not repeated NA NA

    MT 707If field 79 is present, it cannot appear more than twice
    (maximum 2 occurrences).

    C72 MT 537In each occurrence of subsequence C2, field 36B::PSTA
    cannot appear more than twice(maximum 2 occurrences). When
    repeated, one occurrence must have Quantity Type CodeFAMT and the
    other occurrence must have Quantity Type Code AMOR.

    Subsequence C2if field :36B::PSTA is …

    Then one occurrence of:36B::PSTA must be …

    And the other occurrenceof :36B::PSTA must be …

    Repeated :36B::PSTA//FAMT :36B::PSTA//AMOR

    Not repeated NA NA

    MT 564In each occurrence of subsequence E1, field 36B::ENTL
    cannot appear more than twice(maximum 2 occurrences). When
    repeated, one occurrence must have Quantity Type CodeFAMT and the
    other occurrence must have Quantity Type Code AMOR.

    Subsequence E1if field :36B::ENTL is …

    Then one occurrence of:36B::ENTL must be …

    And the other occurrenceof :36B::ENTL must be …

    Repeated :36B::ENTL//FAMT :36B::ENTL//AMOR

    Not repeated NA NA

    MT 565In sequence. D, field 36B::QINS or QREC cannot appear more
    than twice (maximum 2occurrences). When repeated, one occurrence
    must have Quantity Type Code FAMT and theother occurrence must have
    Quantity Type Code AMOR. When used with format option C,
    thequalifiers QINS and QREC cannot be repeated.

    Sequenceif field :36B::QINS or QREC

    is …

    Then one occurrence of:36B::QINS or QREC must

    be …

    And the other occurrenceof :36B::QINS or QRECmust be …

    :36B::QINS//FAMT :36B::QINS//AMORRepeated

    :36B::QREC//FAMT :36B::QREC//FAMT

    Not repeated NA NA

    Chapter 3 Alphanumeric Codes

    22 July 2011 39

  • Note: Therefore the only valid repetitions are:

    :36B::QINS//FAMT

    :36B::QINS//AMOR

    or

    :36B::QREC//FAMT

    :36B::QREC//AMOR

    MT 566In each occurrence of subsequence D1, field 36B::PSTA
    cannot appear more than twice(maximum 2 occurrences). When
    repeated, one occurrence must have Quantity Type CodeFAMT and the
    other occurrence must have Quantity Type Code AMOR.

    Subsequence D1if field :36B::PSTA is …

    Then one occurrence of:36B::PSTA must be …

    And the other occurrenceof :36B::PSTA must be …

    Repeated :36B::PSTA//FAMT :36B::PSTA//AMOR

    Not repeated NA NA

    C73 MT 536A reference to the previously received message must be
    specified for each transaction reported,that is, in each occurrence
    of subsequence B1a Transaction, field 20C::RELA must be presentin
    one and only one occurrence of subsequence B1a1 Linkages; field
    20C::RELA is not allowedin all other occurrences of subsequence
    B1a1.

    MT 537A reference to the previously received message must be
    specified for each transaction reported,that is, in each occurrence
    of subsequence B2 Transaction, field 20C::RELA must be present
    inone and only one occurrence of subsequence B2a Linkages; field
    20C::RELA is not allowed inall other occurrences of subsequence
    B2a.

    MTs 544, 545, 546, 547, and 548A reference to the previously
    received message must be specified, that is, field 20C::RELA mustbe
    present in one and only one occurrence of subsequence A1 Linkages;
    field 20C::RELA is notallowed in all other occurrences of
    subsequence A1.

    C74 MT 537A reference to the previously received message must be
    specified for each transaction reported,that is, in each occurrence
    of sequence C Transaction, field 20C::RELA must be present in
    oneand only one occurrence of subsequence C1 Linkages; field
    20C::RELA is not allowed in allother occurrences of subsequence
    C1.

    C75 MT 104The presence of field 23E in sequence B, depends on
    the presence and content of field 23E insequence A as follows:

    If field 23E is present in sequence A and contains RFDD, then
    field 23E must be present inall occurrences of sequence B.

    If field 23E is present in sequence A and does not contain RFDD,
    then field 23E must notbe present in any occurrence of sequence
    B.

    FIN

    40 Error Codes

  • Note:

    If field 23E is not present in sequence A, then field 23E must
    be present in all occurrencesof sequence B.

    Sequence Aif field 23E is …

    Sequence Bif field 23E is …

    Present and = RFDD Mandatory in all occurrences

    Present and not = RFDD Not allowed

    Not present Mandatory in all occurrences

    See Error codes C94 and C96.

    C76 MT 104Field 50a (option A or K) must be present either in
    sequence A or in each occurrence ofsequence B, but must never be
    present in both sequences, nor absent from both sequences.

    Sequence Aif field 50a (option A or K) is …

    In every occurrence of sequence B,then field 50 (option A or K)
    is …

    Present Not allowed

    Not present Mandatory

    C77 MTs 730, 768, and 769Either field 25 or field 57a, but not
    both, may be present.

    C78 MTs 730, 768, and 769Either field 32D or field 57a, but not
    both, may be present.

    C79 MTs 305 and 601Field 31C may be present only if subfield 3
    of field 23 contains A.

    C80 MT 608The commodity code must be the same for all
    occurrences of the indicated fields in the entiremessage.

    C81 MTs 103, 103+, 202, 202 COV (sequence A), 203, 205, and 205
    COV (sequence A)If field 56a is present, then field 57a must also
    be present.

    C82 MTs 104 and 107In sequence A, if field 23E is present and
    contains RTND, then field 72 must be present. In allother cases
    (that is field 23E is not present, or field 23E does not contain
    RTND), field 72 is notallowed.

    Sequence A

    If field 23E is … Then field 72 is …

    Present and = RTND Mandatory

    Present and not = RTND Not allowed

    Chapter 3 Alphanumeric Codes

    22 July 2011 41

  • Sequence A

    If field 23E is … Then field 72 is …

    Not present Not allowed

    C83 MT 935Either field 23 or field 25, but not both, must be
    present in any repetitive sequence.

    C84 MT 303In sequence A, the presence of field 21 depends on
    field 22A as follows:

    Sequence A

    If field 22A is … Then field 21 is …

    AMNA Mandatory

    AMND Mandatory

    CANC Mandatory

    DUPL Optional

    NEWT Optional

    C85 MT 609Field 68B must be present when the immediately
    preceding field 23 contains SPOTS orFORWARDS.

    C86 MT 609Field 68C must be present when the immediately
    preceding field 23 contains OPTIONS.

    C87 Available.

    C88 MT 305The currency code in subfield 4 of field 23 must be
    the same as the currency code in field 32B.

    C89 MTs 600, 601, 604, 605, 606, 607, 608, and 609A maximum of 6
    decimal digits is permitted in the following: field 32F in MTs 600,
    601, 604, 605,606 and 607; fields 60F, 60M, 61, 62F, 62M, 64 and 65
    in MT 608; and subfield 6 of fields 68Band 68C in MT 609.

    MT 620A maximum of 6 decimal digits is permitted in the
    subfields «amount» of sequence B: field 32F,index 18, field 32R,
    index 19, field 34J, index 21, and of sequence G: field 33J, index
    52, andfield 33J, index 54.

    C90 MTs 700, 710, 720, and 740If field 42a is used, the only
    combinations that are allowed are field 42M (on its own) or field
    42P(on its own) or both fields 42C and 42(A or D).

    FIN

    42 Error Codes

  • Note:

    Note:

    C91 MT 608Subfield 4 of field 61 must not be present.

    C92 MT 303Sequences B and C are mutually exclusive. Field 94A in
    sequence A specifies which type oftransaction is allocated and thus
    which one of the two sequences must be present:

    Sequence Aif field 94A is …

    Then sequence B is … Then sequence C is …

    FORX Mandatory Not allowed

    FXOP Not allowed Mandatory

    C93 MT 600Either sequence B or C, but not both, must be
    present.

    C94 MT 104If field 23E in sequence A is present and contains
    RFDD, then field 119 of the User Headermust be present and contain
    RFDD. If field 23E in sequence A is not present or does not
    containRFDD, then field 119 of the User Header must not be
    present.

    Sequence Aif field 23E is …

    User Headerthen field 119 is …

    Present and = RFDD Mandatory and must contain RFDD

    Present and not = RFDD Not allowed

    Not present Not allowed

    This error code takes precedence over Error codes C75 and
    C96.MTs 503, 504, 505, 506, and 507The User Header is mandatory and
    must contain a field 119 with a valid code that is identical tothat
    contained in subfield 2 of field :22a::COLA//4!c in sequence A.

    The rule 94 must be applied even if the DSS is present in field
    :22F::COLA.

    C95 MT 303In sequence C, the presence of field 30X depends on
    field 23B as follows:

    Sequence C

    If field 23B is … Then field 30X is …

    CLAM or PTAM Mandatory

    CLEU or PTEU Not allowed

    C96 MT 104If field 23E is present in sequence A and contains
    RFDD, then:

    field 21R in sequence A is optional

    fields 21E, 50a (option A or K), 52a, 71F and 71G must not be
    present in sequence B

    Chapter 3 Alphanumeric Codes

    22 July 2011 43

  • Note:

    Note:

    sequence C must not be present

    Otherwise, that is in sequence A, field 23E does not contain
    RFDD or field 23E is not present:

    in sequence A, field 21R must not be present

    and in sequence B, the fields 21E, 50a (option A or K), 52a, 71F
    and 71G are optional

    and sequence C must be present

    Sequence A Sequence B

    If field 23E is … Then field 21R is … And fields 21E,
    50a(option A or K), 52a,71F and 71G are …

    And sequence C is…

    Present and = RFDD Optional Not allowed Not allowed

    Present and not =RFDD

    Not allowed Optional Mandatory

    Not present Not allowed Optional Mandatory

    1. See Error codes D75, C94 and D80.

    2. Error code C96 takes precedence over Error code D80.

    C97 MT 303The presence of sequence D depends on the value of
    field 22A in sequence A as follows:

    Sequence Aif field 22A is …

    Then sequence D is …

    AMNA, AMND, DUPL or NEWT Mandatory

    CANC Optional

    MT 504The presence of sequence D is mandatory when in any
    occurrence of sequence C,subsequence C1 is present and subsequence
    C1a is not present:

    In sequence(s) C Then sequence D is …

    If in one or more occurrence(s) of sequenceC:subsequence C1 is
    present andan internal subsequence C1a is not present

    Mandatory

    See Error code D49.MT 505The presence of sequence C is mandatory
    when in any occurrence of sequence B,subsequence B1 is present and
    subsequence B1a is not present:

    In sequence(s) B Then sequence C is …

    If in one or more occurrence(s) of sequenceB:subsequence B1 is
    present andan internal subsequence B1a is not present

    Mandatory

    FIN

    44 Error Codes

  • Note:

    Note:

    Note:

    See Error code D49.

    C98 MTs 306, 320, 330 , 340, and 620In a sequence, field 15a may
    not be the only field, that is if field 15a is present, then at
    least oneother field in the sequence must be present.

    The following lists the sequences per message type:

    Message type Sequence

    306 I

    320, 330 H

    340 E

    620 H

    C99 MT 303In each occurrence of sequence D, the presence of
    subsequence D3 depends on field 94A ofsequence A as follows:

    Sequence Aif field 94A is …

    Then subsequence D3 is …

    FORX Not allowed

    FXOP Mandatory

    MT 504Sequence E is mandatory when in any occurrence of sequence
    C, subsequence C2 is presentand subsequence C2a is not present.

    In sequence(s) C Then sequence E is …

    If in one or more occurrence(s) of sequenceC:subsequence C2 is
    present and an internalsubsequence C2a is not present

    Mandatory

    See Error code D50.MT 505Sequence D is mandatory when in any
    occurrence of sequence B, subsequence B2 is presentand subsequence
    B2a is not present.

    In sequence(s) B Then sequence D is …

    If in one or more occurrence(s) of sequenceB:subsequence B2 is
    present and an internalsubsequence B2a is not present

    Mandatory

    See Error code D50.

    Chapter 3 Alphanumeric Codes

    22 July 2011 45

  • 3.4.2 D Error CodesNote

    Similar error codes are used by other SWIFT services, such as
    Accord, or Processingfor Euro Banking Association (EBA), and can
    have different meanings. The error codesused by each of the
    services are described in the respective service documentation.

    D00 Not used.

    D01 MT 303If subfield 1 of field 39P contains CURR, the number
    of decimal digits in subfield 3 is checkedagainst the maximum
    allowed for the corresponding currency in subfield 2.

    D02 MTs 304, 360, 361, 362, 364, and 365In sequence A, the
    presence of field 21 depends on field 22A as follows:

    Sequence A

    If field 22A is … Then field 21 is …

    AMND Mandatory

    CANC Mandatory

    DUPL Optional

    NEWT Optional

    MTs 306 and 340In sequence A, the presence of field 21 depends
    on field 22A as follows:

    Sequence A

    If field 22A is … Then field 21 is …

    AMND Mandatory

    CANC Mandatory

    NEWT Optional

    MT 341In sequence A, the presence of field 21 depends on field
    22A as follows:

    Sequence A

    If field 22A is … Then field 21 is …

    AMND Mandatory

    CANC Mandatory

    SETT Optional

    FIN

    46 Error Codes

  • Note:

    Note:

    MT 350In sequence A, if field 22A contains ADVC, then field 21
    is optional; otherwise field 21 ismandatory:

    Sequence A

    If field 22A is … Then field 21 is …

    ADVC Optional

    Not = ADVC Mandatory

    D03 MT 304In sequence A, the presence of fields 17O and 17N
    depend on field 94A as follows:

    Sequence A

    If field 94A is … Then field 17O is … Then field 17N is

    ASET Not allowed Not allowed

    AFWD Mandatory Mandatory

    See also Error codes D04 and D29.MT 535If field :94a:: is
    present in sequence B, then fields :93B::AGGR and :94a::SAFE are
    not allowedin any occurrence of subsequence B1b:

    Sequence Bif field :94a: is …

    Then in any occurrence(s) of subsequenceB1b, field :93B::AGGR
    and field

    :94a::SAFE are …

    Present Not allowed

    Not present Optional

    D04 MT 304In sequence A, the presence of field 17F depends on
    field 17O as follows:

    Sequence A

    If field 17O is … Then field 17F is …

    Y Not allowed

    N Mandatory

    Not present Not allowed

    See also Error codes D03 and D29.MT 535If field :93B::AGGR is
    present in subsequence B1b, then :field 94a::SAFE must be present
    in thesame subsequence B1b:

    Sequence B1bif field :93B::AGGR is …

    Then in same subsequence B1b,field :94a::SAFE is …

    Present Mandatory

    Not present Optional

    Chapter 3 Alphanumeric Codes

    22 July 2011 47

  • D05 MT 535In each occurrence of subsequence B1b, if field
    :93B::AVAI or/and :93B::NAVL is/are present,then :field :93B::AGGR
    must be present in the same occurrence of subsequence B1b.

    MTs 700, 705, 707, 710, 720, 740, and 747Either field 39A or
    field 39B, but not both, may be present.

    D06 MTs 700, 705, 707, 710, and 720Either field 44C or 44D but
    not both, may be present.

    D07 Available.

    D08 MT 670In subsequence A2, either field :95P::SSIR or field
    :94C::SSIR or field :22H::SSIR must bepresent:

    Subsequence A2if field :95P::SSIR is …

    Subsequence A2then field :94C::SSIR is …

    Subsequence A2 then field:22H::SSIR is …

    Present Not allowed Not allowed

    Present Not allowedNot present

    Not present Mandatory

    D09 MT 670In sequence A, field :95P::SUBM must specify the same
    BIC as the Sender in the basic header.If the branch code of the
    Sender’s BIC is XXX, then the branch code is not required in
    field:95P::SUBM. If the branch code of the Sender’s BIC is not XXX,
    then the branch code in field:95P::SUBM must be the same. If the
    branch code of :95P:SUBM is present, then the branchcode of the
    Sender’s BIC must be the same.

    In addition, if the Sender’s BIC is a Test and Training BIC then
    it’s owning master’s registeredBIC with or without a branch code
    could also be specified in field :95P::SUBM Submitting Party.

    D10 Available.

    D11 MT 670In each occurrence of sequence B, if subsequence B1
    contains field :95a::INT2 then :95a::INT1must be present in another
    subsequence B1:

    Within each occurrence of sequence Bin subsequence B1

    if field :95a::INT1 is …

    In the same occurrence of sequence Bthen in another subsequence
    B1

    field :95a::INT2 is …

    Present Optional

    Not present Not allowed

    D12 MT 670In each occurrence of sequence B, in subsequence B1,
    field :95P::BENM or :95Q::BENM or:95R::BENM must be present. All
    three may be present but once only.

    FIN

    48 Error Codes

  • D13 MTs 380 and 381In sequence C, fields 16R and 16S may not be
    the only fields present. If both fields 16R and16S are present,
    then at least one of the other fields of the sequence C must be
    present.

    MTs 503, 504, and 506In subsequence B1, fields 16R and 16S may
    not be the only fields present. If both fields 16Rand 16S are
    present, then at least one other field of the same subsequence must
    be present.

    MT 670In subsequence B2, fields 16R and 16S may not be the only
    fields present. If both fields 16Rand 16S are present, then at
    least one of the other fields of the same subsequence B2 must
    bepresent.

    In sequence C, fields 16R and 16S may not be the only fields
    present. If both fields 16R and16S are present, then at least one
    of the other fields of the sequence C must be present.

    D14 MT 670In subsequence A2, if field :95P::SSIR is not present,
    then in subsequence B2 and sequence C,field :22F:PMTH must not be
    present. In sequence C, field :22F::PMTH is only allowed
    whensubsequence B2, field :22F::PMTH is not present:

    Subsequence A2if field is …:95P::SSIR

    Subsequence B2then field :22F::PMTH is …

    Sequence Cthen field :22F::PMTH is …

    Present Present Not allowed

    Present Not present Optional

    Not present Not allowed Not allowed

    D15 MT 670In each occurrence of subsequence B1, fields
    :95P::ACCW, :95Q::ACCW and :95R::ACCW mayall be present but once
    only.

    In each occurrence of subsequence B1, fields :95P::INT1,
    :95Q::INT1 and :95R::INT1 may all bepresent but once only.

    In each occurrence of subsequence B1, fields :95P::INT2,
    :95Q::INT2 and :95R::INT2 may all bepresent but once only.

    D16 MT 306The presence of subsequence B1 and of sequence C
    depends on the values of Type of Event(subfield 1 of field 22K) in
    sequence A as follows:

    Sequence Aif subfield 1 of field 22K is

    Then subsequence B1is …

    And sequence Cis …

    CLST Optional Optional

    CONF Mandatory Mandatory

    KNIN Not allowed Not allowed

    KNOT Not allowed Not allowed

    OTHR Optional Optional

    TRIG Not allowed Not allowed

    Chapter 3 Alphanumeric Codes

    22 July 2011 49

  • D17 MTs 102 and 102+Field 50a must be present either in sequence
    A or in each occurrence of sequence B, but itmust never be present
    in both sequences, nor be absent from both sequences.

    D18 MT 102 (not 102+)If a field 52a, 26T or 77B is present in
    sequence A, then that field must not be present in anyoccurrence of
    sequence B. When a field 52a, 26T or 77B is present in any
    occurrences ofsequence B, that field must not be present in
    sequence A.

    Sequence Aif field 52a is …

    In each occurrence ofsequence B

    then field 52a is …

    Present Not allowed

    Not present Optional

    Sequence Aif field 26T is …

    In each occurrence ofsequence B

    then field 26T is …

    Present Not allowed

    Not present Optional

    Sequence Aif field 77B is …

    In each occurrence ofsequence B

    then field 77B is …

    Present Not allowed

    Not present Optional

    MT 102+If a field 52A, 26T or 77B is present in sequence A, then
    that field must not be present in anyoccurrence of sequence B. When
    a field 52A, 26T or 77B is in any occurrence of sequence B,that
    field must not be present in sequence A.

    Sequence Aif field 52A is …

    In each occurrence ofsequence B

    then field 52A is …

    Present Not allowed

    Not present Optional

    Sequence Aif field 26T is …

    In each occurrence ofsequence B

    then field 26T is …

    Present Not allowed

    Not present Optional

    Sequence Aif field 77B is …

    In each occurrence ofsequence B

    then field 77B is …

    Present Not allowed

    FIN

    50 Error Codes

  • Note:

    Sequence Aif field 77B is …

    In each occurrence ofsequence B

    then field 77B is …

    Not present Optional

    D19 MT 102+If in the transaction headers the country codes of
    both the Sender’s and Receiver’s BIC arepresent in the list D19_CC
    (see note 2), then in each occurrence of sequence B the
    followingapply:

    If field 57A is not present, then the IBAN format (ISO-13616,
    see note 1) is mandatory insubfield_1 Account of field 59a in this
    occurrence of sequence B.

    If field 57A is present and the country code of the BIC in 57A
    (note) is present in the listD19_CC, then the IBAN format is
    mandatory in subfield_1 Account of field 59a in thisoccurrence of
    sequence B.

    In all other cases, the presence of the IBAN format is optional
    and its format is not validated insubfield_1 Account of field
    59a.

    1. format special validation.

    2. D19_CC list of country codes : AD, AT, BE, BG, BV, CH, CY,
    CZ, DE, DK, EE,ES, FI, FR, GB, GF, GI, GP, GR, HU, IE, IS, IT, LI,
    LT, LU, LV, MC, MQ, MT,NL, NO, PL, PM, PT, RE, RO, SE, SI, SJ, SK,
    SM, TF and VA.

    In transaction headers, In each occurrence of sequence B,

    If country codeof Emitter’s BIC

    present inD19_CC

    And countrycode of

    Receiver’s BICpresent inD19_CC

    And field 57Apresent in this

    occurrenceof sequence B

    And countrycode

    of field 57Ais present in

    D19_CC

    Then in thisoccurrence ofsequence B

    in field 59a the

    format insubfield_1

    Account is …

    Yes Yes No NA Mandatory

    Yes No No NA Optional

    No Yes No NA Optional

    No No No NA Optional

    Yes Yes Yes Yes Mandatory

    Yes No Yes Yes Optional

    No Yes Yes Yes Optional

    No No Yes Yes Optional

    Yes Yes Yes No Optional

    Yes No Yes No Optional

    No Yes Yes No Optional

    No No Yes No Optional

    Chapter 3 Alphanumeric Codes

    22 July 2011 51

  • Note:

    Note:

    Note:

    This validation rule applies to all types of BICs that are
    referenced in field57A: SWIFT BIC, NON-SWIFT BIC, Master, Synonym,
    LIVE destination, Test andTraining destination.

    MT 103+If in the transaction headers the country codes of both
    the Sender’s and Receiver’s BIC arepresent in the list D19_CC (see
    note 2), then in each occurrence of sequence B the
    followingapply:

    If field 57A is not present, then the IBAN format (ISO-13616,
    see note 1) is mandatory insubfield_1 Account of field 59a

    If field 57A is present and the country code of the BIC in 57A
    (note) is present in the listD19_CC, then the IBAN format is
    mandatory in subfield_1 Account of field 59a

    In all other cases, the presence of the IBAN format is optional
    and its format is not validated insubfield_1 Account of field
    59a.

    1. format special validation.

    2. D19_CC list of country codes : AD, AT, BE, BG, BV, CH, CY,
    CZ, DE, DK, EE,ES, FI, FR, GB, GF, GI, GP, GR, HU, IE, IS, IT, LI,
    LT, LU, LV, MC, MQ, MT,NL, NO, PL, PM, PT, RE, RO, SE, SI, SJ, SK,
    SM, TF and VA.

    In transaction headers,

    If country codeof Emitter’s BIC

    present inD19_CC

    and countrycode of

    Receiver’s BICpresent inD19_CC

    and field 57Apresent

    and countrycode

    of field 57Ais present in

    D19_CC

    then in field 59athe

    format insubfield_1

    Account is …

    Yes Yes No NA Mandatory

    Yes No No NA Optional

    No Yes No NA Optional

    No No No NA Optional

    Yes Yes Yes Yes Mandatory

    Yes No Yes Yes Optional

    No Yes Yes Yes Optional

    No No Yes Yes Optional

    Yes Yes Yes No Optional

    Yes No Yes No Optional

    No Yes Yes No Optional

    No No Yes No Optional

    This validation rule applies to all types of BICs that are
    referenced in field57A: SWIFT BIC, NON-SWIFT BIC, Master, Synonym,
    LIVE destination, Test andTraining destination.

    FIN

    52 Error Codes

  • Note:

    D20 MTs 102 and 102+Field 71A must be present either in sequence
    A or in each occurrence of sequence B, but itmust never be present
    in both sequences, nor be absent from both sequences.

    This error code takes precedence over Error codes D50, E13 and
    E15.

    D21 MTs 104 and 107In each occurrence of sequence B, if field
    33B is present, then the currency code or the amount,or both, must
    be different between fields 33B and 32B.

    D22 MT 102 and 102+Field 36 (sequence A or sequence B) must be
    present in the message if there is any sequenceB which contains a
    field 33B with a currency code different from the currency code in
    field 32B;in all other cases field 36 is not allowed in the
    message.

    When a field 36 (sequence A or sequence B) is required, EITHER
    field 36 must be present insequence A and not in any sequence B, OR
    it must be present in every sequence B whichcontains fields 32B and
    33B with different currency codes and must not be present in
    sequenceA or any other sequence B.

    In sequence A In sequence B

    If field 36 is present Then in minimum one occurrence ofsequence
    B field 33B must be present,and currency codes in fields 32B and
    33Bmust be different.

    And field 36 is notallowed in anyoccurrence ofsequence B

    In sequence A In each occurrence of sequence B

    If field 33B is … And currency codesin fields 32B and

    33B are …

    Then field 36 is …

    Equal Not allowedPresent

    Not equal Mandatory

    If field 36 is notpresent

    Not present NA Not allowed

    D23 MT 304The presence of sequence D depends on field 17O as
    follows:

    Sequence Aif field 17O is …

    Then sequence D is …

    Y Not allowed

    N Mandatory

    Not present Not allowed

    D24 MT 306In sequence A, if field 12F contains VANI, then at
    least field 17A or field 17F must contain Y.Both fields may contain
    Y.

    Chapter 3 Alphanumeric Codes

    22 July 2011 53

  • Sequence A

    If field 12F is … And field 17A is … And field 17F is …
    Then thiscombination of

    codes is …

    VANI N N Not allowed

    VANI N Y Allowed

    VANI Y N Allowed

    VANI Y Y Allowed

    Not = VANI NA NA Allowed

    D25 Available.

    D26 MT 306In sequence A, the values allowed for field 12E depend
    on the value of field 12F as follows:

    Sequence A

    If field 12F is … Then the allowed values for field 12E are

    BINA AMER, EURO

    DIGI EURO

    NOTO EURO

    VANI AMER, BERM, EURO

    D27 MT 306In sequence A, the allowed values for subfield 1 of
    field 22K depend on fields 12F and 17A asfollows:

    Sequence A

    If field 12F is … And field 17A is … Then the allowed values
    forsubfield 1 of field 22K are …

    VANI N CONF, CLST, OTHR

    VANI Y CONF, CLST, KNIN, KNOT,OTHR

    Not = VANI N CONF, CLST, TRIG, OTHR

    Not = VANI Y CONF, CLST, KNIN, KNOT,TRIG, OTHR

    FIN

    54 Error Codes

  • Note:

    D28 MT 306In sequence A, the presence of fields 30U and 29H
    depends on the value of subfield 1 of field22K as follows:

    Sequence A

    If subfield 1 of field 22K is…

    Then field 30U is … And field 29H is …

    CONF or CLST Not allowed Not allowed

    Any other value Mandatory Optional

    D29 MT 304The presence of sequence E depends on fields 17F and
    17N as follows:

    Sequence A

    If field 17F is … And field 17N is …Then sequence E is

    Y Y Mandatory

    Y N Not allowed

    Y Not present Not allowed (this case is already
    negativelyacknowledged, see Error codes D03 andD04)

    N Y or N Not allowed

    N Not present Not allowed (this case is already
    negativelyacknowledged, see Error codes D03 andD04)

    Not present Y or N Not allowed

    Not present Not present Not allowed

    See also Error codes D03 and D04.MT 507The presence of sequence
    B depends on the value of field :25D::4!c// in sequence Aand the
    value of field :13A::Link// in subsequence A2 as follows:

    Chapter 3 Alphanumeric Codes

    22 July 2011 55

  • Note:

    Sequence A

    If field:25D::4!c/[8c]/4!c Qualifier is

    And field:25D::REST/[8c]/4!c Data

    SourceScheme [8c] is

    And field:25D::REST/[8c]/

    4!c is …

    SubsequenceA2

    and field:13A::LINK//3!c

    is …Then sequence

    B is …

    :25D::REST//ACCP 503 Optional

    :25D::REST//ACCT 503 Optional

    :25D::REST//ACCP 504 Mandatory

    :25D::REST//ACCT 504 Mandatory

    :25D::REST//ACCP 505 Optional

    :25D::REST//ACCT 505 Optional

    :25D::REST//SUBR NA Optional

    Not present

    :25D::REST//REJT NA Not allowed

    REST

    Present NA NA Optional

    CPRC NA NA NA Not allowed

    IPRC NA NA NA Not allowed

    See Error code D52.MT 567If the message is an instruction status
    or a cancellation request status (:23G:INST or CAST),AND sequence B
    is present, then sequence B should contain a CA option number and
    code(:13A::CAON and :22a::CAOP are mandatory).

    In sequence Aif field :23G:

    is …

    and sequence B is…

    then sequence B,field :13A::CAON is

    and sequence B,field :22a::CAOP is

    Present Mandatory MandatoryINST or CAST

    Not present NA NA

    EVST NA NA NA

    D30 MT 306The presence of sequences D and G depends on the value
    of field 12F in sequence A asfollows:

    Sequence Aif field 12F is …

    Then sequence D is … And sequence G is …

    VANI Mandatory Not allowed

    Not = VANI Not allowed Mandatory

    FIN

    56 Error Codes

  • D31 MT 306If sequence D is present, that is if field 12F in
    sequence A contains VANI (see Error code D30),then the presence of
    fields 30P and 30Q depends on the value of field 12E in sequence A
    asfollows:

    Sequence A Sequence D

    If field 12E is … And field 12E is … Then field 30P is …
    And field 30Q is …

Swift T13 – это типичная ошибка, которая может возникнуть в процессе работы с языком программирования Swift. Код ошибки T13 указывает на проблему, связанную с типами данных. Это одна из наиболее распространенных ошибок, с которой сталкиваются разработчики при создании приложений на Swift.

Основная причина возникновения ошибки T13 — неправильное использование типов данных в коде. Ошибка возникает, когда значение переприсваивается переменной с другим типом данных, чем у переменной. Это может привести к конфликту типов данных, что прерывает выполнение программы и генерирует ошибку T13.

Пример:

let number: Int = 5

let message: String = «Hello, world!»

number = message // Ошибка T13 — значение типа String не может быть присвоено переменной типа Int

Чтобы устранить ошибку T13, необходимо внимательно следить за типами данных, которые используются в коде. Убедитесь, что значения, которые вы присваиваете переменным, имеют правильный тип данных. Если вы сталкиваетесь с ошибкой T13, исправьте конфликт типов, изменяя типы данных на соответствующие их значениям.

Содержание

  1. Код ошибки T13 в Swift: что они значат и как расшифровать
  2. Частые причины возникновения ошибки T13 в Swift
  3. Устранение ошибки T13 в Swift: эффективные методы и советы
  4. Как избежать ошибок T13 в Swift: профилактические меры
  5. Советы по отладке и исправлению ошибок T13 в Swift

Код ошибки T13 в Swift: что они значат и как расшифровать

Коды ошибок T13 в Swift являются сообщениями об ошибках, которые могут возникать в процессе разработки на языке программирования Swift. Каждый код ошибки имеет свой уникальный идентификатор, который помогает разработчику понять, в чем именно проблема и как ее устранить.

Расшифровка кодов ошибок T13 позволяет быстро определить причину возникновения ошибки и принять соответствующие меры для ее исправления. Чтобы расшифровать код ошибки T13, необходимо обратиться к документации по Swift или использовать инструменты разработки, такие как Xcode.

Ошибки T13 в Swift могут иметь разные причины, связанные с синтаксическими ошибками, проблемами с памятью, некорректными операторами и другими аспектами языка программирования. Расшифровка кодов ошибок T13 помогает разработчику точно определить и исправить причину ошибки, что облегчает и ускоряет процесс разработки.

Когда код ошибки T13 в Swift появляется, наиболее эффективным способом его устранения является использование документации по Swift или поиск по ошибке в Интернете. В документации можно найти описание ошибки и рекомендации по ее исправлению. Также полезно изучить примеры кода, в которых подобная ошибка уже возникала и была успешно исправлена.

Важно помнить, что коды ошибок T13 в Swift являются инструментом для помощи разработчику в процессе разработки. Их расшифровка и исправление ошибок помогают повысить качество кода и улучшить процесс разработки программного обеспечения.

Частые причины возникновения ошибки T13 в Swift

Ошибки T13 в Swift могут возникать по разным причинам, связанным с неправильным использованием операторов, функций и структур языка. Рассмотрим некоторые частые причины возникновения этой ошибки:

  • Несовпадение типов данных: Ошибка T13 может возникать, когда происходит попытка присвоения значения одного типа другому типу данных, которые несовместимы. Например, попытка присвоить строковое значение переменной типа Int. В таком случае необходимо проверить и исправить типы данных, чтобы они соответствовали друг другу.
  • Отсутствие необходимого значения: Другой причиной ошибки T13 может быть отсутствие значения, которое ожидается в определенном контексте. Например, использование переменной, которая не была инициализирована. В этом случае необходимо проверить, что все переменные и константы были корректно инициализированы перед использованием.
  • Ошибки в логике программы: Иногда ошибка T13 может возникать из-за ошибок в логике программы. Например, неправильное условие в операторе if, которое приводит к неправильному выполнению кода. В таком случае необходимо внимательно проверить логику программы и исправить ошибку в условии или операторе.
  • Неправильное использование функций и методов: Еще одной причиной ошибки T13 может быть неправильное использование функций и методов языка Swift. Например, передача неправильных аргументов в функцию или вызов метода у несуществующего объекта. В таком случае необходимо проверить, что все аргументы функции передаются в правильном порядке и соответствуют ожидаемым типам данных.

Чтобы избежать ошибки T13 в Swift, рекомендуется тщательно проверять код на соответствие типов данных, правильность инициализации переменных и констант, а также логику программы. При возникновении ошибки необходимо анализировать сообщение об ошибке и проверить соответствующий участок кода на предмет возможных ошибок.

Устранение ошибки T13 в Swift: эффективные методы и советы

Ошибка T13 в языке программирования Swift возникает, когда компилятор обнаруживает попытку присвоить значение оптимального типа одной переменной другой переменной с несовместимым типом данных. Эта ошибка может возникнуть, например, при попытке присвоить значение переменной типа Int переменной типа String.

Чтобы устранить ошибку T13 в Swift, следует выполнить следующие действия:

  1. Тщательно проверьте код наличия ошибки. Проверьте все строки кода, где происходит присваивание значений переменным.
  2. Убедитесь, что типы данных переменных совместимы. Проверьте, что тип данных исходной переменной совпадает с типом данных переменной, к которой она присваивается.
  3. Если типы данных не совместимы, вы можете:
    • Изменить тип данных одной из переменных, чтобы сделать его совместимым с другой переменной.
    • Добавить преобразование типов данных с помощью оператора as или других операторов Swift, чтобы привести переменную к необходимому типу.
  4. Проверьте другие строки кода, которые могут вызывать эту ошибку. Иногда ошибка может быть вызвана цепочкой других ошибок или неправильных значений переменных.
  5. Запустите тесты и проверьте, исправлена ли ошибка T13. Убедитесь, что ваш код работает без ошибок и выдает ожидаемые результаты.

Соблюдение этих методов и советов поможет вам успешно устранить ошибку T13 в языке программирования Swift и продолжить разработку вашего приложения без проблем.

Как избежать ошибок T13 в Swift: профилактические меры

Ошибки T13 в Swift могут быть причиной непредвиденного поведения программы и могут затруднить отладку кода. Чтобы избежать этих ошибок, следует принять несколько профилактических мер:

  1. Внимательно изучите документацию: перед тем, как приступить к разработке приложения на Swift, рекомендуется тщательно изучить официальную документацию, чтобы понять особенности языка и избежать типичных ошибок.
  2. Корректно используйте опционалы: опционалы в Swift позволяют обрабатывать значения, которые могут быть nil. Правильное использование опционалов и проверка на nil помогут предотвратить ошибки T13, связанные с неправильным доступом к опциональным значениям.
  3. Тщательно управляйте жизненным циклом объектов: утечки памяти и неправильное управление жизненным циклом объектов могут привести к ошибкам T13. Рекомендуется аккуратно использовать атрибуты weak и unowned, а также изучить паттерны проектирования, такие как Singleton и Dependency Injection, чтобы правильно управлять объектами.
  4. Тестирование и отладка: проведение комплексного тестирования и отладки кода помогает выявлять и исправлять ошибки раньше, до того, как они станут причиной ошибок T13. Рекомендуется использовать инструменты для тестирования и отладки, такие как Xcode, чтобы облегчить процесс исправления ошибок.

Вывод: чтобы избежать ошибок T13 в Swift, необходимо более внимательно относиться к процессу разработки, правильно использовать опционалы, управлять жизненным циклом объектов и проводить тестирование и отладку кода. Это позволит улучшить качество программы и предотвратить возникновение ошибок T13.

Советы по отладке и исправлению ошибок T13 в Swift

Ошибка T13 в Swift является ошибкой времени выполнения и может быть вызвана различными причинами, такими как неправильное использование операторов, отсутствие объявления переменной или неправильное приведение типов данных. Вот несколько советов по отладке и исправлению ошибок T13:

  1. Проверьте правильность написания кода. Одна из самых распространенных причин ошибки T13 — это опечатка или неправильное написание имени переменной или функции. Откройте внимательно свой код и проверьте все имена переменных и функций на наличие ошибок.
  2. Проверьте правильность использования операторов и приведение типов данных. Ошибка T13 может возникнуть, если вы используете неправильный оператор или приводите типы данных неправильно. Убедитесь, что вы используете правильные операторы и правильно приводите типы данных в своем коде.
  3. Используйте отладку. Отладка — это процесс поиска и исправления ошибок в коде. В Swift вы можете использовать отладчик Xcode, чтобы отслеживать значение переменных и шагать по коду по одной строке. Используйте отладчик, чтобы поймать ошибку T13 и увидеть, какие значения переменных вызывают проблему.
  4. Используйте команду «print». Если вы не можете использовать отладчик, чтобы отслеживать значение переменных, вы можете использовать команду «print» в своем коде, чтобы выводить значения переменных в консоль. Например, вы можете написать «print(myVariable)» чтобы увидеть значение переменной myVariable в консоли.
  5. Изучите документацию. Если вы столкнулись с ошибкой T13, которую не можете исправить, обратитесь к официальной документации по Swift, чтобы узнать больше о возможных причинах ошибки и способах ее исправления. Документация может помочь вам понять, как правильно использовать операторы и функции в Swift и предоставить примеры кода для исправления ошибки.

Важно помнить, что код T13 может иметь различные причины и способы исправления в зависимости от контекста. При отладке ошибок T13 в Swift важно быть терпеливым и систематичным, а также использовать доступные инструменты, такие как отладчик и команду «print». Надеюсь, эти советы помогут вам отладить и исправить ошибки T13 в своем коде на Swift!

Понравилась статья? Поделить с друзьями:

Интересное по теме:

  • Код ошибки ssangyong p1254
  • Код ошибки swift t12
  • Код ошибки spn 157 fm1 18
  • Код ошибки spn 633 fmi 31
  • Код ошибки spn 108 fmi 4

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии