#
# Copyright 2014 MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
use 5.008;
use strict;
use warnings;
package MongoDB::Error;
# ABSTRACT: MongoDB Driver Error classes
# Portions adapted from Throwable.pm by Ricardo Signes
use version;
our $VERSION = 'v1.8.1';
use Moo;
use Carp;
use MongoDB::_Types qw(
ErrorStr
);
use Scalar::Util ();
use Sub::Quote ();
use Exporter 5.57 qw/import/;
use namespace::clean -except => ['import'];
my $ERROR_CODES;
BEGIN {
$ERROR_CODES = {
BAD_VALUE => 2,
UNKNOWN_ERROR => 8,
NAMESPACE_NOT_FOUND => 26,
EXCEEDED_TIME_LIMIT => 50,
COMMAND_NOT_FOUND => 59,
WRITE_CONCERN_ERROR => 64,
NOT_MASTER => 10107,
DUPLICATE_KEY => 11000,
DUPLICATE_KEY_UPDATE => 11001, # legacy before 2.6
DUPLICATE_KEY_CAPPED => 12582, # legacy before 2.6
UNRECOGNIZED_COMMAND => 13390, # mongos error before 2.4
NOT_MASTER_NO_SLAVE_OK => 13435,
NOT_MASTER_OR_SECONDARY => 13436,
CANT_OPEN_DB_IN_READ_LOCK => 15927,
};
}
use constant $ERROR_CODES;
# Export error codes for use by end-users; this is unusual for Moo, but
# probably sufficiently helpful to justify it
our @EXPORT = keys %$ERROR_CODES;
our %_HORRIBLE_HACK;
use overload (
q{""} => sub {
my $self = shift;
return sprintf( "%s: %s", ref($self), $self->message );
},
fallback => 1
);
has message => (
is => 'ro',
isa => ErrorStr,
default => 'unspecified error',
);
has 'previous_exception' => (
is => 'ro',
default => Sub::Quote::quote_sub(q<
if (defined $MongoDB::Error::_HORRIBLE_HACK{ERROR}) {
$MongoDB::Error::_HORRIBLE_HACK{ERROR}
} elsif (defined $@ and (ref $@ or length $@)) {
$@;
} else {
undef;
}
>),
);
sub throw {
my ($inv) = shift;
if (Scalar::Util::blessed($inv)) {
Carp::confess "throw called on MongoDB::Error object with arguments" if @_;
die $inv;
}
local $_HORRIBLE_HACK{ERROR} = $@;
my $throwable = @_ == 1 ? $inv->new( message => $_[0] ) : $inv->new(@_);
die $throwable;
}
#--------------------------------------------------------------------------#
# Subclasses with attributes included inline below
#--------------------------------------------------------------------------#
package MongoDB::DatabaseError;
use Moo;
use Types::Standard qw(Num);
use namespace::clean;
extends("MongoDB::Error");
has result => (
is => 'ro',
does => 'MongoDB::Role::_DatabaseErrorThrower',
required => 1,
);
has code => (
is => 'ro',
isa => Num,
builder => '_build_code',
);
sub _build_code { return MongoDB::Error::UNKNOWN_ERROR() }
package MongoDB::DocumentError;
use Moo;
use Types::Standard qw(Any);
use namespace::clean;
extends("MongoDB::Error");
has document => (
is => 'ro',
isa => Any,
required => 1,
);
package MongoDB::UsageError;
use Moo;
use Types::Standard qw(Str);
use namespace::clean -except => 'meta';
extends("MongoDB::Error");
use overload (
q{""} => sub {
my $self = shift;
return sprintf( "%s: %s%s", ref($self), $self->message, $self->trace );
},
fallback => 1
);
has trace => (
is => 'ro',
isa => Str,
);
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
my $args = $class->SUPER::BUILDARGS(@_);
# start stack trace above where throw() is called (or
# at the top of the stack), so it works like confess
my $i = 0;
while ( my @caller = caller($i) ) {
$i++;
last if $caller[0] eq "MongoDB::Error";
}
local $Carp::CarpLevel = caller( $i + 1 ) ? $i + 1 : $i;
$args->{trace} = Carp::longmess('');
return $args;
};
# Connection errors
package MongoDB::ConnectionError;
use Moo;
use namespace::clean;
extends 'MongoDB::Error';
package MongoDB::HandshakeError;
use Moo;
use namespace::clean;
extends 'MongoDB::ConnectionError';
package MongoDB::NetworkError;
use Moo;
use namespace::clean;
extends 'MongoDB::ConnectionError';
# Timeout errors
package MongoDB::TimeoutError;
use Moo;
use namespace::clean;
extends 'MongoDB::Error';
package MongoDB::ExecutionTimeout;
use Moo;
use namespace::clean;
extends 'MongoDB::TimeoutError';
package MongoDB::NetworkTimeout;
use Moo;
use namespace::clean;
extends 'MongoDB::TimeoutError';
# Database errors
package MongoDB::DuplicateKeyError;
use Moo;
use namespace::clean;
extends 'MongoDB::DatabaseError';
sub _build_code { return MongoDB::Error::DUPLICATE_KEY() }
package MongoDB::NotMasterError;
use Moo;
use namespace::clean;
extends 'MongoDB::DatabaseError';
sub _build_code { return MongoDB::Error::NOT_MASTER() }
package MongoDB::WriteError;
use Moo;
use namespace::clean;
extends 'MongoDB::DatabaseError';
package MongoDB::WriteConcernError;
use Moo;
use namespace::clean;
extends 'MongoDB::DatabaseError';
sub _build_code { return MongoDB::Error::WRITE_CONCERN_ERROR() }
# Other errors
package MongoDB::AuthError;
use Moo;
use namespace::clean;
extends 'MongoDB::Error';
package MongoDB::CursorNotFoundError;
use Moo;
use namespace::clean;
extends 'MongoDB::Error';
package MongoDB::DecodingError;
use Moo;
use namespace::clean;
extends 'MongoDB::Error';
package MongoDB::GridFSError;
use Moo;
use namespace::clean;
extends 'MongoDB::Error';
package MongoDB::InternalError;
use Moo;
use namespace::clean;
extends 'MongoDB::Error';
package MongoDB::ProtocolError;
use Moo;
use namespace::clean;
extends 'MongoDB::Error';
package MongoDB::SelectionError;
use Moo;
use namespace::clean;
extends 'MongoDB::Error';
#--------------------------------------------------------------------------#
# Private error classes
#--------------------------------------------------------------------------#
package MongoDB::_CommandSizeError;
use Moo;
use Types::Standard qw(Int);
use namespace::clean;
extends("MongoDB::Error");
has size => (
is => 'ro',
isa => Int,
required => 1,
);
1;
=pod
=encoding UTF-8
=head1 NAME
MongoDB::Error - MongoDB Driver Error classes
=head1 VERSION
version v1.8.1
=head1 SYNOPSIS
use MongoDB::Error;
MongoDB::Error->throw("a generic error");
MongoDB::DatabaseError->throw(
message => $string,
result => $hashref,
);
=head1 DESCRIPTION
This class defines a hierarchy of exception objects.
=head1 USAGE
Unless otherwise explicitly documented, all driver methods throw exceptions if
an error occurs.
To catch and handle errors, the L<Try::Tiny> and L<Safe::Isa> modules
are recommended:
use Try::Tiny;
use Safe::Isa; # provides $_isa
try {
$coll->insert( $doc )
}
catch {
if ( $_->$_isa("MongoDB::DuplicateKeyError" ) ) {
...
}
else {
...
}
};
To retry failures automatically, consider using L<Try::Tiny::Retry>.
=head1 EXCEPTION HIERARCHY
MongoDB::Error
|
|->MongoDB::AuthError
|
|->MongoDB::ConnectionError
| |
| |->MongoDB::HandshakeError
| |
| |->MongoDB::NetworkError
|
|->MongoDB::CursorNotFoundError
|
|->MongoDB::DatabaseError
| |
| |->MongoDB::DuplicateKeyError
| |
| |->MongoDB::NotMasterError
| |
| |->MongoDB::WriteError
| |
| |->MongoDB::WriteConcernError
|
|->MongoDB::DecodingError
|
|->MongoDB::DocumentError
|
|->MongoDB::GridFSError
|
|->MongoDB::InternalError
|
|->MongoDB::ProtocolError
|
|->MongoDB::SelectionError
|
|->MongoDB::TimeoutError
| |
| |->MongoDB::ExecutionTimeout
| |
| |->MongoDB::NetworkTimeout
|
|->MongoDB::UsageError
All classes inherit from C<MongoDB::Error>.
All error classes have the attribute:
=over 4
=item *
message — a text representation of the error
=back
=head2 MongoDB::AuthError
This error indicates a problem with authentication, either in the underlying
mechanism or a problem authenticating with the server.
=head2 MongoDB::ConnectionError
Errors related to network connections.
=head3 MongoDB::HandshakeError
This error is thrown when a connection has been made, but SSL or authentication
handshakes fail.
=head3 MongoDB::NetworkError
This error is thrown when a socket error occurs, when the wrong number of bytes
are read, or other wire-related errors occur.
=head2 MongoDB::CursorNotFoundError
This error indicates that a cursor timed out on a server.
=head2 MongoDB::DatabaseError
Errors related to database operations. Specifically, when an error of this type
occurs, the driver has received an error condition from the server.
Attributes include:
=over 4
=item *
result — response from a database command; this must impliement the C<last_errmsg> method
=item *
code — numeric error code; see L</ERROR CODES>; if no code was provided by the database, the C<UNKNOWN_ERROR> code will be substituted instead
=back
=head3 MongoDB::DuplicateKeyError
This error indicates that a write attempted to create a document with a
duplicate key in a collection with a unique index. The C<result> attribute is
a result object.
=head3 MongoDB::NotMasterError
This error indicates that a write or other state-modifying operation was
attempted on a server that was not a primary. The C<result> attribute is
a L<MongoDB::CommandResult> object.
=head3 MongoDB::WriteError
Errors indicating failure of a write command. The C<result> attribute is
a result object.
=head3 MongoDB::WriteConcernError
Errors indicating failure of a write concern. The C<result> attribute is a
result object.
=head2 MongoDB::DecodingError
This error indicates a problem during BSON decoding; it wraps
the error provided by the underlying BSON encoder. Note: Encoding errors
will be thrown as a L</MongoDB::DocumentError>.
=head2 MongoDB::DocumentError
This error indicates a problem with a document to be inserted or replaced into
the database, or used as an update document.
Attributes include:
=over 4
=item *
document — the document that caused the error
=back
=head2 MongoDB::GridFSError
Errors related to GridFS operations, such a corrupted file.
=head2 MongoDB::InternalError
Errors that indicate problems in the driver itself, typically when something
unexpected is detected. These should be reported as potential bugs.
=head2 MongoDB::ProtocolError
Errors related to the MongoDB wire protocol, typically problems parsing a
database response packet.
=head2 MongoDB::SelectionError
When server selection fails for a given operation, this is thrown. For example,
attempting a write when no primary is available or reading with a specific mode
and tag set and no servers match.
=head2 MongoDB::TimeoutError
These errors indicate a user-specified timeout has been exceeded.
=head3 MongoDB::ExecutionTimeout
This error is thrown when a query or command fails because C<max_time_ms> has
been reached. The C<result> attribute is a L<MongoDB::CommandResult> object.
=head3 MongoDB::NetworkTimeout
This error is thrown when a network operation exceeds a timeout, typically
C<connect_timeout_ms> or C<socket_timeout_ms>.
=head2 MongoDB::UsageError
Indicates invalid arguments or configuration options. Not all usage errors
will throw this — only ones originating directly from the MongoDB::* library
files. Some type and usage errors will originate from the L<Type::Tiny>
library if the objects are used incorrectly.
=head1 ERROR CODES
The following error code constants are automatically exported by this module.
BAD_VALUE => 2,
UNKNOWN_ERROR => 8,
NAMESPACE_NOT_FOUND => 26,
EXCEEDED_TIME_LIMIT => 50,
COMMAND_NOT_FOUND => 59,
WRITE_CONCERN_ERROR => 64,
NOT_MASTER => 10107,
DUPLICATE_KEY => 11000,
DUPLICATE_KEY_UPDATE => 11001, # legacy before 2.6
DUPLICATE_KEY_CAPPED => 12582, # legacy before 2.6
UNRECOGNIZED_COMMAND => 13390, # mongos error before 2.4
NOT_MASTER_NO_SLAVE_OK => 13435,
NOT_MASTER_OR_SECONDARY => 13436,
CANT_OPEN_DB_IN_READ_LOCK => 15927,
This is a very, very small subset of error codes possible from the server,
but covers some of the more common ones seen by drivers.
B<Note>:
=over 4
=item *
Only C<MongoDB::DatabaseError> objects have a C<code> attribute.
=item *
The database uses multiple write concern error codes. The driver maps them all to WRITE_CONCERN_ERROR for consistency and convenience.
=back
=head1 AUTHORS
=over 4
=item *
David Golden <david@mongodb.com>
=item *
Rassi <rassi@mongodb.com>
=item *
Mike Friedman <friedo@friedo.com>
=item *
Kristina Chodorow <k.chodorow@gmail.com>
=item *
Florian Ragwitz <rafl@debian.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is Copyright (c) 2018 by MongoDB, Inc.
This is free software, licensed under:
The Apache License, Version 2.0, January 2004
=cut
__END__
# vim: ts=4 sts=4 sw=4 et: